1. 설계 목적
LLM은 당진시청 공식 자료에서 검색된 chunk와 출처 metadata만 사용합니다.
홈페이지 내용을 모델에 학습시키지 않고, 수집/검색/RAG로 답변합니다.
URL, 게시일, 담당부서, 연락처, 공공누리 정보를 함께 제공합니다.
2. 전체 구조
공식 자료 지식베이스를 중심으로 여러 서비스 채널이 같은 검색 API와 답변 API를 사용합니다.
3. 계층별 구성
4. 수집 및 색인 프로세스
| 구분 | 정책 |
|---|---|
| 허용 범위 | /kor.do, /kor/, /cop/bbs/, /prog/, 공식 페이지 첨부파일 |
| 차단 범위 | 로그인, 본인확인, 국민신문고, 민원상담 신청/조회, 자유게시판, 칭찬합시다, 홍보게시판, 외부 도메인 |
| 변경 감지 | 정리된 본문 기준 body_hash가 같으면 chunk와 embedding 재생성 생략 |
5. 저장 구조
canonical_url, title, published_at, department, body_hash, body_text
document_id, url, filename, mime_type, extracted text
document_id, content, content_for_embedding, vector(1024), metadata
started_at, finished_at, status, pages_seen, pages_saved, errors
[당진시청]
메뉴경로: ...
제목: ...
게시일: ...
담당부서: ...
연락처: ...
출처: ...
본문 chunk 내용...
6. 검색 API 설계
검색 API는 LLM 답변 생성과 분리해 챗봇, 관리자, 출처 탐색, 아웃바운드 후보 생성에서 재사용합니다.
| 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 답변 생성과 채널
대화 이력, 후속 질문, 버튼/빠른 응답 UI를 고려하되 답변 근거는 Search API 결과로 제한합니다.
관리자 화면, 내부 업무 도구, 배치 작업에서 질문 텍스트를 넣고 답변 텍스트와 출처를 받습니다.
8. 아웃바운드 예측 및 링크형 답변
사용자가 먼저 질문하기 전에 자주 발생할 질문이나 안내가 필요한 상황을 예측해 짧은 안내와 링크를 제공합니다.
짧은 답변에는 핵심 요약과 상세 링크를 제공하고, 전체 정보와 공식 출처는 링크 페이지에서 확인하게 합니다.
9. 동적 답변 페이지
링크로 제공되는 페이지는 고정 FAQ가 아니라 질문과 답변이 1:1로 매칭되는 동적 페이지입니다.
{
"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. 캐싱과 개인 식별 변수 분리
동일한 질문은 캐싱하고, 개인 식별 정보는 답변 본문에 직접 섞지 않고 변수로 분리합니다.
| 항목 | 처리 방식 |
|---|---|
| 공통 질문 의도 | 정규화 후 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 템플릿을 입힙니다.
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. 구현 우선순위
Search API 분리
현재 RAG 검색 로직을 LLM 호출 없이 사용할 수 있는 API로 노출합니다.
Answer Page 저장 모델 추가
질문별 answer_md, sources, cache_key를 저장하고 링크로 조회할 수 있게 합니다.
Markdown/Text 렌더러 추가
답변 본문은 Markdown으로 저장하고 공통 HTML 템플릿으로 렌더링합니다.
캐싱과 변수 치환
질문 정규화, 개인정보 변수 분리, cache_key 기반 답변 재사용을 구현합니다.
관리자 문자 미리보기
개발 단계에서는 실제 발송 없이 draft와 preview만 제공합니다.