dangjin-rag architecture

당진시청 공식 자료 RAG 전체 아키텍처 설계

공개 자료 수집, 지식베이스 구축, 검색 API, 로컬 LLM 답변, 챗봇/텍스트 서비스, 아웃바운드 링크형 답변, 동적 답변 페이지, 캐싱, 관리자 문자 미리보기를 하나의 구조로 정리한 기준 설계 문서입니다.

1. 설계 목적

공식 자료 기반

LLM은 당진시청 공식 자료에서 검색된 chunk와 출처 metadata만 사용합니다.

파인튜닝 없음

홈페이지 내용을 모델에 학습시키지 않고, 수집/검색/RAG로 답변합니다.

출처 필수

URL, 게시일, 담당부서, 연락처, 공공누리 정보를 함께 제공합니다.

2. 전체 구조

공식 자료 지식베이스를 중심으로 여러 서비스 채널이 같은 검색 API와 답변 API를 사용합니다.

당진시청 공식 자료 HTML, 게시글, 첨부파일, 공공누리 정보
수집/정제 Crawler, robots.txt, URL filter, extractor
지식베이스 PostgreSQL, pgvector, metadata
검색/LLM 서비스 Search API, RAG Answer, Ollama
사용 채널 API, Streamlit, 챗봇, 텍스트 서비스, 링크형 안내

3. 계층별 구성

수집 계층
robots.txt URL 정규화 차단 URL 정책 첨부파일 다운로드
지식화 계층
본문 추출 공공누리 감지 chunk 생성 embedding body_hash 변경 감지
서비스 계층
Search API Ask API Answer Page API Outbound Draft API Admin Preview API
채널 계층
Streamlit 챗봇 텍스트 LLM 서비스 문자 링크 안내 관리자 화면

4. 수집 및 색인 프로세스

Crawl 허용 URL, robots.txt, delay, max pages
Extract 본문, 제목, 게시일, 담당부서, 첨부파일
Normalize 공백 정리, 중복 제거, body_hash
Index chunk, passage embedding, pgvector 저장
구분 정책
허용 범위 /kor.do, /kor/, /cop/bbs/, /prog/, 공식 페이지 첨부파일
차단 범위 로그인, 본인확인, 국민신문고, 민원상담 신청/조회, 자유게시판, 칭찬합시다, 홍보게시판, 외부 도메인
변경 감지 정리된 본문 기준 body_hash가 같으면 chunk와 embedding 재생성 생략

5. 저장 구조

documents

canonical_url, title, published_at, department, body_hash, body_text

attachments

document_id, url, filename, mime_type, extracted text

chunks

document_id, content, content_for_embedding, vector(1024), metadata

crawl_jobs

started_at, finished_at, status, pages_seen, pages_saved, errors

[당진시청]
메뉴경로: ...
제목: ...
게시일: ...
담당부서: ...
연락처: ...
출처: ...

본문 chunk 내용...

6. 검색 API 설계

검색 API는 LLM 답변 생성과 분리해 챗봇, 관리자, 출처 탐색, 아웃바운드 후보 생성에서 재사용합니다.

질문/검색어 q, top_k, filters, channel
Hybrid Search vector top 30 + keyword top 30
RRF 병합 중복 병합, score 재계산
검색 결과 chunk, score, URL, 게시일, 담당부서
API 목적 출력
GET /search?q=... LLM 없이 검색 결과만 제공 chunks, sources, score
POST /ask 검색 결과 기반 LLM 답변 생성 answer, sources, retrieved_chunks
POST /answer-pages 질문별 동적 답변 페이지 생성 page_id, public_url, cache_key

7. RAG 답변 생성과 채널

사용자 질문 API, 챗봇, 텍스트 서비스
Search API 공식 자료 검색
Ollama gemma4:e4b, temperature 0.1
답변 + 출처 확인 불가 시 정해진 문구 반환
챗봇 채널

대화 이력, 후속 질문, 버튼/빠른 응답 UI를 고려하되 답변 근거는 Search API 결과로 제한합니다.

텍스트 기반 LLM 서비스

관리자 화면, 내부 업무 도구, 배치 작업에서 질문 텍스트를 넣고 답변 텍스트와 출처를 받습니다.

8. 아웃바운드 예측 및 링크형 답변

사용자가 먼저 질문하기 전에 자주 발생할 질문이나 안내가 필요한 상황을 예측해 짧은 안내와 링크를 제공합니다.

예측 대상 공지, 민원, 신청기간, 담당부서 문의
예상 질문 template 또는 관리자 입력
RAG 답변 직접 답변 + 참고 요약
동적 답변 페이지 질문:답변 1:1 상세 페이지
짧은 안내 요약 + 상세 링크 + 공식 출처 안내
운영 원칙

짧은 답변에는 핵심 요약과 상세 링크를 제공하고, 전체 정보와 공식 출처는 링크 페이지에서 확인하게 합니다.

9. 동적 답변 페이지

링크로 제공되는 페이지는 고정 FAQ가 아니라 질문과 답변이 1:1로 매칭되는 동적 페이지입니다.

answer_md LLM이 만든 질문별 답변 Markdown
variable replace {{name}}, {{case_no}} 치환
HTML template 레이아웃, 출처, 안내문 적용
동적 HTML 사용자에게 링크로 제공
{
  "page_id": "ans_20260511_xxxxx",
  "question": "당진시 무인민원발급기 안내 알려줘",
  "answer_md": "## 답변\n...\n\n## 참고할 내용\n...",
  "sources": [{ "title": "...", "url": "...", "department": "..." }],
  "variables": { "recipient_name": "{{recipient_name}}" },
  "cache_key": "question_hash + filters_hash + source_hash"
}

10. 캐싱과 개인 식별 변수 분리

동일한 질문은 캐싱하고, 개인 식별 정보는 답변 본문에 직접 섞지 않고 변수로 분리합니다.

원 질문 개인명, 접수번호 등 포함 가능
정규화 개인값을 placeholder로 분리
cache_key 질문 의도 + 필터 + 자료 hash
공통 답변 패턴 개인정보 없는 answer_md 저장
변수 치환 렌더링 직전에 replace
항목 처리 방식
공통 질문 의도 정규화 후 answer_cache로 재사용
개인 식별 변수 {{recipient_name}}, {{case_no}} 같은 placeholder로 분리
공식 출처 URL, 게시일, 담당부서, 연락처를 metadata로 별도 저장

11. 문자 발송 관리자 미리보기

개발 단계에서는 실제 문자 발송을 하지 않고, 관리자 화면에서 발신 내용과 링크를 확인합니다.

문자 발송 비활성화

SMS provider 호출은 막고, 모든 발송 요청은 draft 상태로만 저장합니다.

관리자 검수

문구, 링크, 개인정보 변수 치환 결과, 공식 출처를 실제 발송 전 확인합니다.

영역 내용
문자 미리보기 요약 문구, 상세 링크, 공식 출처 안내
근거 자료 검색된 문서명, URL, 게시일, 담당부서
발송 상태 draft, previewed, approved, disabled_in_dev

12. Markdown/Text 기반 HTML 렌더링

LLM은 답변 본문과 참고 요약을 Markdown 또는 일반 텍스트로 만들고, 서버 스크립트가 HTML 템플릿을 입힙니다.

LLM output answer_md, summary_text
Renderer Markdown parse, sanitize, variables replace
Template header, source list, CTA, footer
HTML response 빠른 렌더링, cache 가능

13. 확장 데이터 모델 초안

테이블 핵심 필드 설명
answer_cache cache_key, normalized_question, answer_md, source_hash, expires_at 동일 질문/동일 자료 기준의 LLM 답변 재사용
answer_pages id, question, answer_md, summary_text, source_ids, cache_key 질문:답변 1:1 링크 페이지 원본 데이터
answer_variables page_id, variable_key, variable_value, scope 개인 식별 가능 변수를 본문과 분리 관리
outbound_drafts channel, recipient_ref, message_text, answer_page_id, status 개발 단계 문자 발송 미리보기와 관리자 검수
search_logs query, filters, result_count, channel, created_at 검색 품질 개선과 질문 패턴 분석

14. 구현 우선순위

1

Search API 분리

현재 RAG 검색 로직을 LLM 호출 없이 사용할 수 있는 API로 노출합니다.

2

Answer Page 저장 모델 추가

질문별 answer_md, sources, cache_key를 저장하고 링크로 조회할 수 있게 합니다.

3

Markdown/Text 렌더러 추가

답변 본문은 Markdown으로 저장하고 공통 HTML 템플릿으로 렌더링합니다.

4

캐싱과 변수 치환

질문 정규화, 개인정보 변수 분리, cache_key 기반 답변 재사용을 구현합니다.

5

관리자 문자 미리보기

개발 단계에서는 실제 발송 없이 draft와 preview만 제공합니다.