insurance-chatbot / README.md
๊น€๋ฏผ๊ฒฝ
์‹œ๋‚˜๋ฆฌ์˜ค ์ „์ฒด ์‹ค์ธก ์žฌ๊ฒ€์ฆ: ์‘๋‹ต ํ™•์ธ ํ›„ ๋‹ค์Œ ์งˆ๋ฌธ ์„ค๊ณ„
3e8566c
metadata
title: Insurance Chatbot
emoji: ๐Ÿฅ
colorFrom: indigo
colorTo: purple
sdk: docker
app_port: 7860
pinned: false

AI TMR Assistant โ€” Tool Routing ๊ณ ๋„ํ™”

Intelligent Tool Routing์œผ๋กœ ์ •ํ™•๋„๋ฅผ ๊ฐœ์„ ํ•˜๊ณ , Scalable Tool Architecture๋กœ ์šด์˜ ํšจ์œจ๊ณผ ํ™•์žฅ์„ฑ์„ ๋™์‹œ์— ํ™•๋ณดํ•จ


1. ๋ฌธ์ œ

12๊ฐœ ๋ณดํ—˜ ์ƒํ’ˆ ร— 9๊ฐœ ๊ธฐ๋Šฅ(์กฐํšŒยท์‚ฐ์ถœยท์‹ฌ์‚ฌยท๋ณด์žฅยท์ฒญ๊ตฌ ๋“ฑ) = 54๊ฐœ ๋„๊ตฌ. ๋„๊ตฌ๊ฐ€ ๋งŽ์•„์ง€๋ฉด์„œ ์„ธ ๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ์ƒ๊น€.

๋ฌธ์ œ ์›์ธ ์˜ํ–ฅ
์˜คํ˜ธ์ถœ ์œ ์‚ฌ ๋„๊ตฌ ํ˜ผ๋™ (premium_estimate โ†” plan_options) ์ž˜๋ชป๋œ ๋‹ต๋ณ€
๋น„์šฉ ์ฆ๊ฐ€ ๋งค ์š”์ฒญ๋งˆ๋‹ค 54๊ฐœ ์Šคํ‚ค๋งˆ๊ฐ€ LLM ์ปจํ…์ŠคํŠธ์— ํฌํ•จ๋จ ํ† ํฐ ๋‚ญ๋น„
์ง€์—ฐ ์ฆ๊ฐ€ ์ปจํ…์ŠคํŠธ ๊ธธ์ด์— ๋น„๋ก€ํ•˜์—ฌ ์‘๋‹ต ์‹œ๊ฐ„์ด ์ƒ์Šนํ•จ UX ์ €ํ•˜

๋„๊ตฌ 10๊ฐœ๋ฅผ ๋„˜์œผ๋ฉด ์ •ํ™•๋„๊ฐ€ ๋–จ์–ด์ง€๊ณ , 37๊ฐœ ๊ธฐ์ค€ ~6,200 ํ† ํฐ์ด ์†Œ๋น„๋จ (์ฐธ๊ณ ). "์ „๋ถ€ ๋„˜๊ธฐ์ง€ ๋ง๊ณ  ํ•„์š”ํ•œ ๊ฒƒ๋งŒ ๊ฒ€์ƒ‰ํ•ด์„œ ๋„˜๊ธฐ์ž" โ€” ์ด๊ฒƒ์ด RAG-MCP ํŒจํ„ด์˜ ํ•ต์‹ฌ์ž„ (์ฐธ๊ณ ).


2. ์„ค๊ณ„ โ€” ๋‘ ์ถ•์˜ ์ „๋žต

์ด ํ”„๋กœ์ ํŠธ๋Š” ๋‘ ๊ฐœ์˜ ์ถ•์œผ๋กœ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•จ.

์ „๋žต ์ถ• ํ•ต์‹ฌ ๋ชฉํ‘œ
Intelligent Tool Routing ์˜คํ˜ธ์ถœ์„ ์ค„์ด๊ณ  ์ •ํ™•ํ•œ ํ˜ธ์ถœ๋งŒ ๋‚จ๊น€ ์ •ํ™•๋„ยท๋น„์šฉยท์ง€์—ฐ ๊ฐœ์„ 
Scalable Tool Architecture ์‹ ๊ทœ ๋„๊ตฌ ์ถ”๊ฐ€๊ฐ€ ์šด์˜ ๋ถ€๋‹ด์ด ๋˜์ง€ ์•Š๋„๋ก ์ž๋™ํ™” ํ™•์žฅ์„ฑยท์šด์˜ ํšจ์œจ

์•„๋ž˜๋Š” ๋‘ ์ถ•์ด ์‹ค์ œ ์‹œ์Šคํ…œ์—์„œ ์–ด๋–ป๊ฒŒ ์—ฐ๊ฒฐ๋˜๋Š”์ง€๋ฅผ ๋‚˜ํƒ€๋ƒ„.

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                Intelligent Tool Routing                  โ”‚
โ”‚                                                         โ”‚
โ”‚  ์‚ฌ์šฉ์ž ์งˆ๋ฌธ                                              โ”‚
โ”‚      โ–ผ                                                  โ”‚
โ”‚  [Guardrail] โ”€โ”€โ”€ ๋น„๋ณดํ—˜ ์งˆ๋ฌธ ์ฐจ๋‹จ โ”€โ”€โ†’ ๊ฑฐ์ ˆ ์‘๋‹ต            โ”‚
โ”‚      โ”‚ (ํ†ต๊ณผ)                                            โ”‚
โ”‚      โ–ผ                                                  โ”‚
โ”‚  [Tool Card ๋งค์นญ] โ”€โ”€โ”€ ChromaDB ๋ฉ€ํ‹ฐ๋ฒกํ„ฐ โ†’ Top-5 ์ถ”์ถœ      โ”‚
โ”‚      โ–ผ                                                  โ”‚
โ”‚  [LLM Tool Call] โ”€โ”€โ”€ ํ›„๋ณด ์ค‘ ์ตœ์ข… ์„ ํƒ โ†’ ์‹คํ–‰              โ”‚
โ”‚                                                         โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                          โ–ฒ
                          โ”‚ Vector Index ์ฐธ์กฐ
                          โ”‚
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚              Scalable Tool Architecture                  โ”‚
โ”‚                                                         โ”‚
โ”‚  ์ƒˆ Tool ์ถ”๊ฐ€ โ†’ Tool Card ์ž‘์„ฑ โ†’ ์ž„๋ฒ ๋”ฉ ์ž๋™ ์ƒ์„ฑ          โ”‚
โ”‚                                  โ†’ Vector Index ์ž๋™ ๊ฐฑ์‹  โ”‚
โ”‚                                                         โ”‚
โ”‚  Validation: Recall@k ํ‰๊ฐ€ โ†’ ์ˆ˜์น˜ ๊ธฐ๋ฐ˜ ์˜์‚ฌ๊ฒฐ์ • ๊ทผ๊ฑฐ        โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

3. ์ถ• โ‘  โ€” Intelligent Tool Routing

3-1. 3๋‹จ๊ณ„ ํ•„ํ„ฐ๋ง์œผ๋กœ 54๊ฐœ๋ฅผ 5๊ฐœ๋กœ ์ค„์ž„

๋‹จ๊ณ„ ๋ชจ๋“ˆ ๊ธฐ๋Šฅ ์†๋„
Guardrail ์ •๊ทœ์‹(L1) + ์ž„๋ฒ ๋”ฉ(L2) ํƒˆ์˜ฅยท๋น„๋ณดํ—˜ ์งˆ๋ฌธ ์‚ฌ์ „ ์ฐจ๋‹จ <5ms
Tool Search ChromaDB ๋ฉ€ํ‹ฐ๋ฒกํ„ฐ 54๊ฐœ โ†’ Top-K ํ›„๋ณด ์ถ”์ถœ ~10ms
LLM Selection bind_tools() ํ›„๋ณด ์ค‘ ์ตœ์ข… ๋„๊ตฌ ์„ ํƒยทํ˜ธ์ถœ 1~5s

Guardrail์ด ๋จผ์ € ๋™์ž‘ํ•˜๋ฏ€๋กœ "์˜ค๋Š˜ ๋‚ ์”จ ์–ด๋•Œ?" ๊ฐ™์€ ์งˆ๋ฌธ์€ ๋ฒกํ„ฐ ๊ฒ€์ƒ‰์ด๋‚˜ LLM ํ˜ธ์ถœ ์—†์ด ์ฆ‰์‹œ ์ฐจ๋‹จ๋จ.

3-2. Tool Card๋กœ ๊ฒ€์ƒ‰ ์ •ํ™•๋„๋ฅผ ๋†’์ž„

LLM ๋„๊ตฌ description์€ ๋ณดํ†ต ํ•œ๋‘ ์ค„์ด๋ผ, ์œ ์‚ฌ ๋„๊ตฌ๋ผ๋ฆฌ ๋ฒกํ„ฐ๊ฐ€ ๊ฑฐ์˜ ๊ฐ™์•„์ ธ์„œ ๊ตฌ๋ถ„์ด ์–ด๋ ค์›€. ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋„๊ตฌ๋งˆ๋‹ค ToolCard๋ฅผ ์ž‘์„ฑํ•˜์—ฌ ์ž„๋ฒ ๋”ฉ ํ‘œ๋ฉด์„ ํ™•์žฅํ•จ.

ToolCard(
    name="premium_estimate",
    purpose="๋‚˜์ดยท์„ฑ๋ณ„์„ ์ž…๋ ฅํ•ด ํŠน์ • ์ƒํ’ˆ์˜ ์˜ˆ์ƒ ์›” ๋ณดํ—˜๋ฃŒ๋ฅผ ์‚ฐ์ถœํ•œ๋‹ค.",
    when_to_use=("๋ณดํ—˜๋ฃŒ ์–ผ๋งˆ์•ผ?", "40์„ธ ๋‚จ์„ฑ ๋ณดํ—˜๋ฃŒ ๊ณ„์‚ฐํ•ด์ค˜"),
    when_not_to_use=("๋‚ฉ์ž… ํ”Œ๋žœ์ด ๊ถ๊ธˆํ•˜๋‹ค โ†’ plan_options ์‚ฌ์šฉ",),
    tags=("๋ณดํ—˜๋ฃŒ", "์‚ฐ์ถœ"),
)
ํ•„๋“œ ์ž„๋ฒ ๋”ฉ ํฌํ•จ ์—ญํ• 
purpose O ๋„๊ตฌ์˜ ํ•ต์‹ฌ ๊ธฐ๋Šฅ์„ ํ•œ ๋ฌธ์žฅ์œผ๋กœ ์„ค๋ช…
when_to_use O ์‹ค์ œ ์‚ฌ์šฉ์ž ๋ฐœํ™” ์˜ˆ์‹œ โ†’ ๊ฒ€์ƒ‰ ํ‘œ๋ฉด ํ™•์žฅ
tags O ๋„๋ฉ”์ธ ํ‚ค์›Œ๋“œ โ†’ ํด๋Ÿฌ์Šคํ„ฐ๋ง ๋ณด์กฐ
when_not_to_use X ํ˜ผ๋™ ๊ฐ€๋Šฅํ•œ ๋„๊ตฌ ์•ˆ๋‚ด โ†’ LLM ์ตœ์ข… ์„ ํƒ ์‹œ์—๋งŒ ์‚ฌ์šฉ

when_not_to_use๋ฅผ ์ž„๋ฒ ๋”ฉ์—์„œ ์ œ์™ธํ•˜๋Š” ์ด์œ : ํƒ€ ๋„๊ตฌ ์ด๋ฆ„("premium_estimate ์‚ฌ์šฉ")์ด ํฌํ•จ๋˜๋ฉด ๋ฒกํ„ฐ๊ฐ€ ์˜ค์—ผ๋จ. Tool-DE (Lu et al., 2025) ablation์—์„œ๋„ negative example ํฌํ•จ ์‹œ ์„ฑ๋Šฅ์ด ์ €ํ•˜๋จ.

3-3. Multi-Vector ์ธ๋ฑ์‹ฑ

๊ฐ ToolCard ํ•„๋“œ๋ฅผ ๋ณ„๋„ ๋ฌธ์„œ๋กœ ChromaDB์— ์ธ๋ฑ์‹ฑํ•˜๊ณ , ๊ฒ€์ƒ‰ ์‹œ tool๋ณ„ max score๋กœ ์ง‘๊ณ„ํ•จ. ๋‹จ์ผ ๋ฒกํ„ฐ๋กœ ํ•ฉ์น˜๋ฉด ์—ฌ๋Ÿฌ ์˜ˆ์‹œ์˜ ํ‰๊ท ์œผ๋กœ ํฌ์„๋˜์ง€๋งŒ, ์ด ๋ฐฉ์‹์€ ColBERT ๋“ฑ multi-vector ๋ชจ๋ธ๊ณผ ๋™์ผํ•œ ์›๋ฆฌ๋กœ ํฌ์„ ์—†์ด ์ •ํ™•ํ•œ ๋งค์นญ์ด ๊ฐ€๋Šฅํ•จ (Pinecone).


4. ์ถ• โ‘ก โ€” Scalable Tool Architecture

4-1. ๋„๊ตฌ ์ถ”๊ฐ€๊ฐ€ ์šด์˜ ๋ถ€๋‹ด์ด ๋˜์ง€ ์•Š๋„๋ก

์ƒˆ Tool ์ถ”๊ฐ€ โ†’ Tool Card ์ž‘์„ฑ โ†’ ์ž„๋ฒ ๋”ฉ ์ž๋™ ์ƒ์„ฑ โ†’ ์ฆ‰์‹œ ๊ฒ€์ƒ‰ ๋Œ€์ƒ์— ํฌํ•จ
๋ฐฉ์‹ ์ ˆ์ฐจ ์„œ๋ฒ„ ์žฌ์‹œ์ž‘
์ •์  ๋“ฑ๋ก Tool ํ•จ์ˆ˜ + ToolCard โ†’ ์„œ๋ฒ„ ์žฌ์‹œ์ž‘ ํ•„์š”
๋Ÿฐํƒ€์ž„ ํ•ซ๋ฆฌ๋กœ๋“œ Tool ํ•จ์ˆ˜ + API ํ˜ธ์ถœ ๋ถˆํ•„์š”

ToolRegistry๊ฐ€ ๋™์  ๊ด€๋ฆฌํ•˜๊ณ , ๋ณ€๊ฒฝ ์‹œ ChromaDB ์žฌ์ธ๋ฑ์‹ฑ์„ ์ž๋™ ํŠธ๋ฆฌ๊ฑฐํ•จ.

4-2. ์ฝ”๋“œ ๋ณ€๊ฒฝ ์—†์ด ์šด์˜ ์ค‘ ํŠœ๋‹

Admin Dashboard(/admin/tools)์—์„œ ToolCard๋ฅผ ์ˆ˜์ •ํ•˜๋ฉด ์ฆ‰์‹œ ์ฑ—๋ด‡์— ๋ฐ˜์˜๋จ. ๋ฐฐ์น˜ Recall ํ‰๊ฐ€์™€ LLM ๋ถ„์„์„ ๋‚ด์žฅํ•˜์—ฌ, ์ˆ˜์ • ์ „ํ›„ ์„ฑ๋Šฅ ์ฐจ์ด๋ฅผ ๋ฐ”๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Œ.

Admin UI์—์„œ when_to_use ๋ฌธ์žฅ ์ˆ˜์ •
    โ†“  [์ €์žฅ & ๋ฐ˜์˜] ํด๋ฆญ
โ‘  ๋ฉ”๋ชจ๋ฆฌ REGISTRY ์—…๋ฐ์ดํŠธ + ChromaDB ์žฌ์ธ๋ฑ์‹ฑ
โ‘ก data/toolcard_overrides.json ์ €์žฅ (์„œ๋ฒ„ ์žฌ์‹œ์ž‘ ํ›„์—๋„ ์œ ์ง€)
โ‘ข ๋ฒ„์ „ ์ด๋ ฅ ๊ธฐ๋ก โ†’ ๋ฌธ์ œ ์‹œ ๋กค๋ฐฑ ๊ฐ€๋Šฅ

4-3. Validation โ€” ๊ฐ์ด ์•„๋‹Œ ์ˆ˜์น˜๋กœ ํŒ๋‹จ

scripts/eval_tool_recall.py๋กœ Recall@k, MRR, Hit@1์„ ์ •๋Ÿ‰ ์ธก์ •ํ•จ. Admin Dashboard ํ€ต ํ…Œ์ŠคํŠธ ํƒญ์—์„œ๋„ ๊ฐœ๋ณ„ ๋„๊ตฌ์˜ ๋ฐฐ์น˜ Recall ํ‰๊ฐ€์™€ LLM ์‹คํŒจ ๋ถ„์„์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Œ.

python -m scripts.eval_tool_recall --compare    # k=1,3,5,7,10 ๋น„๊ตํ‘œ
python -m scripts.eval_tool_recall --verbose     # ์˜คํŒ ์‚ฌ๋ก€ ์ƒ์„ธ

5. ๊ฒฐ๊ณผ

79๊ฐœ ํ…Œ์ŠคํŠธ ์ฟผ๋ฆฌ(tool-call 64๊ฐœ + no-call 15๊ฐœ) ํ‰๊ฐ€ ๊ฒฐ๊ณผ:

์ง€ํ‘œ k=1 k=3 k=5 (์šด์˜) k=7 k=10
Recall@k 96.9% 100% 100% 100% 100%
Hit@1 96.9% โ€” 96.9% โ€” 96.9%
MRR 0.969 0.984 0.984 โ€” 0.984
No-Call Acc โ€” โ€” 80.0% โ€” 80.0%
  • k=1 ๋ฏธํƒ 2๊ฑด: ์œ ์‚ฌ ๋„๊ตฌ ๊ฒฝ๊ณ„ ์‚ฌ๋ก€ (coverage_detail โ†” benefit_amount, renewal_projection โ†” renewal_notice)
  • k=3๋ถ€ํ„ฐ Recall 100% โ€” 64๊ฐœ tool-call ์ฟผ๋ฆฌ๊ฐ€ ์ „๋ถ€ Top-3 ์•ˆ์— ํฌํ•จ๋จ
  • no-call ์˜คํŒ 3๊ฑด: ์œ ์‚ฌ๋„ 0.86~0.88๋กœ ๊ฒฝ๊ณ„์— ๊ฑธ๋ฆฌ์ง€๋งŒ, Guardrail์—์„œ ์‚ฌ์ „ ์ฐจ๋‹จ๋˜๋ฏ€๋กœ ์‹ค์šด์˜์—์„œ๋Š” Tool Search์— ๋„๋‹ฌํ•˜์ง€ ์•Š์Œ

54๊ฐœ โ†’ 5๊ฐœ๋กœ 90% ์ถ•์†Œํ•ด๋„ Recall@5 = 100%, MRR = 0.98. ์ •ํ™•๋„๋ฅผ ์œ ์ง€ํ•˜๋ฉด์„œ ๋น„์šฉ๊ณผ ์ง€์—ฐ์„ ๋™์‹œ์— ์ค„์ž„.

5-1. ๋ฉ€ํ‹ฐํ„ด ์‹œ๋‚˜๋ฆฌ์˜ค ์‹คํ–‰ ๊ฒฐ๊ณผ

5๊ฐœ TMR ์‹ค์ „ ์ƒ๋‹ด ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ๊ตฌ์ถ•ํ•˜์—ฌ end-to-end ๊ฒ€์ฆ์„ ์ˆ˜ํ–‰ํ•จ.

# ์‹œ๋‚˜๋ฆฌ์˜ค ํ„ด ํ•ต์‹ฌ ๊ฒ€์ฆ ํฌ์ธํŠธ ์‚ฌ์šฉ๋œ ๋„๊ตฌ
1 ๊ธฐ๊ฐ€์ž… ๊ณ„์•ฝ์ž ์•” ์ง„๋‹จ โ†’ ์ฒญ๊ตฌ 4 ๊ณ„์•ฝ ์กฐํšŒ(2๊ฑด ์œ ์ง€, ๊ณ„์•ฝ์ผยท๋งŒ๋ฃŒ์ผยท๊ฐฑ์‹ ์ผ) โ†’ ์ง์ „ ์กฐํšŒํ•œ ์•”๋ณดํ—˜ ๊ธฐ์ค€ ์ฒญ๊ตฌ ์•ˆ๋‚ด(๊ฐ€์ž… ๋ถˆ๊ฐ€ ์•„๋‹˜) โ†’ ์ฒญ๊ตฌ ํ•„์š” ์„œ๋ฅ˜ โ†’ ๊ธฐ๊ฐ€์ž… ๊ธฐ๋ฐ˜ ์ถ”๊ฐ€ ๋ณด์žฅ ์ถ”์ฒœ customer_contract_lookup, event_eligibility_check, claim_required_forms, product_search
2 ๊ธฐ๊ฐ€์ž… ๊ณ„์•ฝ์ž ์ถ”๊ฐ€ ์ƒํ’ˆ ์„ค๊ณ„ 4 ๊ณ„์•ฝ ํ™•์ธ(55์„ธยท์—ฌ์„ฑยท3๊ฑด ์œ ์ง€) โ†’ ์น˜๋งค ๋ณด์žฅ ์ถ”๊ฐ€ ์‹œ ์ค‘๋ณต ์•„๋‹Œ ์ƒํ’ˆ โ†’ ์น˜๋งค๊ฐ„๋ณ‘ vs ์‹ค์†์น˜๋งค 55์„ธ ์—ฌ์„ฑ ๋ณดํ—˜๋ฃŒ ๋น„๊ต โ†’ ๋ณด์œ  3๊ฑด ํ•ฉ์‚ฐ ์›” ๋ณดํ—˜๋ฃŒ(๋งฅ๋ฝ ์‚ฌ์šฉ) customer_contract_lookup, product_search, premium_compare, premium_estimate
3 ํ•ด์ง€๋œ ๋ณดํ—˜ ๋ถ€ํ™œ + ๋Œ€์•ˆ 4 ์œ ์ง€/ํ•ด์ง€ ๊ตฌ๋ถ„(ํ•ด์ง€์ผ ํ‘œ์‹œ) โ†’ ๋ถ€ํ™œ ์กฐ๊ฑด(3๋…„ยท์—ฐ์ฒด๋ณดํ—˜๋ฃŒ ๋“ฑ) โ†’ 60์„ธ ์—ฌ์„ฑ ๋Œ€์•ˆ ์•”๋ณดํ—˜ โ†’ ์œ ์ง€ ์ค‘ ์ข…์‹ ๋ณดํ—˜ ๋ณด์žฅ ๋‚ด์šฉ customer_contract_lookup, underwriting_reinstatement_rule, product_search, coverage_summary
4 ๊ณ ์œ„ํ—˜ ์ง์—… + ์œ ๋ณ‘๋ ฅ ์‹ฌ์‚ฌ 4 ๋ณตํ•ฉ ์กฐ๊ฑด(์ง์—…ยท๋ณ‘๋ ฅ) ์ธ์‹ โ†’ ํ• ์ฆ ์ง๊ตฐ ํ™•์ธ โ†’ ์ฒซ๋‚ ๋ถ€ํ„ฐ์•”๋ณดํ—˜ ๋ณด์žฅ ์ƒ์„ธ โ†’ ๊ฐ„ํŽธ์‹ฌ์‚ฌ ๊ฑด๊ฐ•๋ณดํ—˜ underwriting_precheck, underwriting_high_risk_job_check, coverage_detail, product_search
5 ์‹œ๋‹ˆ์–ด ์ข…ํ•ฉ ์„ค๊ณ„ 4 70์„ธ ์•„๋ฒ„์ง€(๋‚จ์„ฑ) ์‚ฌ๋งยท์น˜์•„ ์ƒํ’ˆ ์ถ”์ฒœ โ†’ ๊ฑด๊ฐ•ํ•ด์ง€๋Š”์ข…์‹  ์—ฐ๊ธˆ์ „ํ™˜ โ†’ ๋“ ๋“ ํ•œ์‹ค๋ฒ„์น˜์•„ 70์„ธ ๊ฐ€์ž…ยท๋ณด์žฅ โ†’ ์ง์ „ ๋‘ ์ƒํ’ˆ ํ•ฉ์‚ฐ ๋ณดํ—˜๋ฃŒ(70์„ธ ๋‚จ์„ฑ) product_search, coverage_summary, premium_estimate

๊ณ„์•ฝ์ž ์ •๋ณด ์ฒ˜๋ฆฌ:

  • ๊ณ„์•ฝ์ž ์ด๋ฆ„์œผ๋กœ customer_contract_lookup ํ˜ธ์ถœ โ†’ ๊ณ„์•ฝ์žIDยท์„ฑ๋ณ„(๋‚จ์„ฑ/์—ฌ์„ฑ)ยท๋‚˜์ด + ๋ณด์œ  ๊ณ„์•ฝ(์œ ์ง€/ํ•ด์ง€) ์ฆ‰์‹œ ํ™•์ธ
  • ๊ณ„์•ฝ ์ •๋ณด์— ๋ณดํ—˜ ์šฉ์–ด ์ ์šฉ: ๊ณ„์•ฝ์ƒํƒœ(์œ ์ง€ยทํ•ด์ง€ยท์‹คํšจยท๋งŒ๊ธฐ), ๊ณ„์•ฝ์ผ, ๋งŒ๋ฃŒ์ผ, ํ•ด์ง€์ผ, ๊ฐฑ์‹ ์ผ
  • ๋ฐ˜ํ™˜ ๋ฐ์ดํ„ฐ์—์„œ ์ „ํ™”๋ฒˆํ˜ธ ๋“ฑ PII๋ฅผ ์†Œ์Šค ๋ ˆ๋ฒจ์—์„œ ํ•„ํ„ฐ๋ง (_safe_customer / _safe_contract)
  • ๊ธฐ๊ฐ€์ž… ์ƒํ’ˆ์—์„œ ์งˆ๋ณ‘ ์ง„๋‹จ ์‹œ โ†’ ๊ฐ€์ž… ๋ถˆ๊ฐ€๊ฐ€ ์•„๋‹Œ ๋ณดํ—˜๊ธˆ ์ฒญ๊ตฌ ์ ˆ์ฐจ ์•ˆ๋‚ด๋กœ ์ „ํ™˜
  • ๋ณด์œ  ๊ณ„์•ฝ ๊ธฐ๋ฐ˜ ์ค‘๋ณต ๊ฐ€์ž… ์—ฌ๋ถ€ ํ™•์ธ ํ›„ ์ถ”๊ฐ€ ์ƒํ’ˆ ์ถ”์ฒœ
  • ๋Œ€ํ™” ๋‚ด๋‚ด ๊ณ„์•ฝ์ž ๋งฅ๋ฝ ์œ ์ง€ (๊ฐ™์€ ID/์ด๋ฆ„์„ ์žฌ์š”๊ตฌํ•˜์ง€ ์•Š์Œ)

์ถœ๋ ฅ ํ’ˆ์งˆ ๊ด€๋ฆฌ:

  • ์ƒํ’ˆ์ฝ”๋“œ(B00...) ์ถœ๋ ฅ ๊ฐ€๋“œ๋ ˆ์ผ์—์„œ ์ž๋™ ์ œ๊ฑฐ
  • ๋‚ด๋ถ€ ๋„๊ตฌ๋ช…(snake_case) ์ถœ๋ ฅ ๊ฐ€๋“œ๋ ˆ์ผ์—์„œ ์ž๋™ ์ œ๊ฑฐ
  • ๋ฉด์ฑ… ๋ฌธ๊ตฌ ์ค‘๋ณต ๋ฐฉ์ง€ (LLM ์ƒ์„ฑ๋ถ„์ด ์žˆ์œผ๋ฉด ๊ฐ€๋“œ๋ ˆ์ผ ์ถ”๊ฐ€ ์ƒ๋žต)
  • ์‘๋‹ต ์ตœ๋Œ€ 7์ค„, ํ•ต์‹ฌ ์ •๋ณด๋งŒ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์ „๋‹ฌ

ํ›„์† ๋‹จ๋‹ต ์ฒ˜๋ฆฌ:

  • "์•„๋ฒ„์ง€" โ†’ ๋‚จ์„ฑ์œผ๋กœ ์ธ์‹, "์–ด๋จธ๋‹ˆ" โ†’ ์—ฌ์„ฑ์œผ๋กœ ์ธ์‹
  • query_rewriter๊ฐ€ 1~3๊ธ€์ž ๋‹จ๋‹ต์„ ์ด์ „ ๋งฅ๋ฝ์— ํ•ฉ์ณ์„œ ์™„์ „ํ•œ ์งˆ๋ฌธ์œผ๋กœ ์žฌ์ž‘์„ฑ

5-2. ์‹œ๋‚˜๋ฆฌ์˜ค ํ„ด๋ณ„ ๊ฒ€์ฆ ํฌ์ธํŠธ (๋ฉ€ํ‹ฐํ„ด ํ’ˆ์งˆ ์ฒดํฌ)

๋ฉ€ํ‹ฐํ„ด ์‹œ๋‚˜๋ฆฌ์˜ค ์‹คํ–‰ ์‹œ ๋งค ํ„ด๋งˆ๋‹ค ์•„๋ž˜๋ฅผ ํ™•์ธํ•˜๋ฉด, ๋งฅ๋ฝ ์ดํ•ดยท์ง์ „ ์‘๋‹ต ๊ธฐ๋ฐ˜ ๋‹ต๋ณ€ ์—ฌ๋ถ€๋ฅผ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ์Œ.

์‹œ๋‚˜๋ฆฌ์˜ค ํ„ด ์‚ฌ์šฉ์ž ์งˆ๋ฌธ ์ง์ „ ๋งฅ๋ฝ ์ฑ—๋ด‡์ด ํ•ด์•ผ ํ•  ์ผ ๊ฒ€์ฆ ํฌ์ธํŠธ
1. ๊น€๋ฏผ์ˆ˜ ์•” ์ง„๋‹จ 1 ๊ณ„์•ฝ์ž ๊น€๋ฏผ์ˆ˜๋‹˜ ๊ณ„์•ฝ ์กฐํšŒํ•ด์ค˜ ์—†์Œ customer_contract_lookup(์ด๋ฆ„=๊น€๋ฏผ์ˆ˜) ๊ณ„์•ฝ 2๊ฑด ์œ ์ง€(์•”+์น˜์•„), ๊ณ„์•ฝ์ผยท๋งŒ๋ฃŒ์ผ ํ‘œ๊ธฐ
1 2 ๊ฐ‘์ƒ์„ ์•” ์ง„๋‹จ๋ฐ›์•˜๋Š”๋ฐ ๊ฐ€์ž… ์ค‘์ธ ์•”๋ณดํ—˜์œผ๋กœ ๋ณดํ—˜๊ธˆ ์ฒญ๊ตฌ ๊ฐ€๋Šฅํ•ด? ๊น€๋ฏผ์ˆ˜ 2๊ฑด ์œ ์ง€(์น˜์•„+์•”) event_eligibility_check โ†’ ์ฒญ๊ตฌ ์•ˆ๋‚ด(๊ฐ€์ž… ๋ถˆ๊ฐ€ ์•„๋‹˜) ๊ธฐ๊ฐ€์ž… ์•”๋ณดํ—˜ ๊ธฐ์ค€ ์ฒญ๊ตฌ ๊ฐ€๋Šฅ ์—ฌ๋ถ€ยท์ ˆ์ฐจ ์•ˆ๋‚ด
1 3 ์ฒญ๊ตฌ ์ ˆ์ฐจ๋ž‘ ํ•„์š”ํ•œ ์„œ๋ฅ˜ ์•Œ๋ ค์ค˜ ์ง์ „์— ์ฒญ๊ตฌ ๊ฐ€๋Šฅ ์•ˆ๋‚ดํ•จ claim_guide ์ฒญ๊ตฌ์„œ๋ฅ˜ยท๋ฐฉ๋ฒ•ยท์ฒ˜๋ฆฌ๊ธฐ๊ฐ„, ์ง์ „ ๋Œ€ํ™” ๋งฅ๋ฝ ์œ ์ง€
1 4 ์ง€๊ธˆ ๊ฐ€์ž…ํ•œ ์ƒํ’ˆ ์™ธ์— ์ถ”๊ฐ€๋กœ ๋„ฃ์œผ๋ฉด ์ข‹์„ ๋ณด์žฅ ์žˆ์–ด? ๊น€๋ฏผ์ˆ˜ ๋ณด์œ (์น˜์•„ยท์•”) ์ค‘๋ณต ํ™•์ธ ํ›„ ์ถ”๊ฐ€ ๋ณด์žฅ ์ถ”์ฒœ ๊ธฐ๊ฐ€์ž… ๊ธฐ๋ฐ˜ ์ค‘๋ณต ์•„๋‹Œ ์ƒํ’ˆ๋งŒ ์ถ”์ฒœ
2. ์œค์ง€์€ ์ถ”๊ฐ€ ์„ค๊ณ„ 1 ๊ณ„์•ฝ์ž ์œค์ง€์€๋‹˜ ๊ณ„์•ฝ ์กฐํšŒํ•ด์ค˜ ์—†์Œ customer_contract_lookup(์ด๋ฆ„=์œค์ง€์€) 55์„ธ ์—ฌ์„ฑ, 3๊ฑด ์œ ์ง€, ๊ณ„์•ฝ์ผยท๋งŒ๋ฃŒ์ผยท๊ฐฑ์‹ ์ผ
2 2 ์น˜๋งค ๋ณด์žฅ์„ ์ถ”๊ฐ€ํ•˜๊ณ  ์‹ถ์€๋ฐ, ์ง€๊ธˆ ๊ฐ€์ง„ ์ƒํ’ˆ์ด๋ž‘ ์•ˆ ๊ฒน์น˜๋Š” ์น˜๋งค๋ณดํ—˜ ์žˆ์–ด? ์œค์ง€์€ 3๊ฑด(๊ฐ„ํŽธ๊ฑด๊ฐ•ยท์น˜์•„ยท์ข…์‹ ) product_search(์น˜๋งค) + ์ค‘๋ณต ์—ฌ๋ถ€ ํŒ๋‹จ ์น˜๋งค ์ƒํ’ˆ 2์ข…, ๊ธฐ๊ฐ€์ž…๊ณผ ๊ฒน์น˜์ง€ ์•Š๋Š” ๊ฒƒ๋งŒ
2 3 ์น˜๋งค๊ฐ„๋ณ‘๋ณดํ—˜์ด๋ž‘ ์‹ค์†์น˜๋งค๋ณดํ—˜ ์ฐจ์ด๊ฐ€ ๋ญ์•ผ? 55์„ธ ์—ฌ์„ฑ ๊ธฐ์ค€ ๋ณดํ—˜๋ฃŒ๋„ ๋น„๊ตํ•ด์ค˜ ์œค์ง€์€ 55์„ธ ์—ฌ์„ฑ coverage_summary + premium_estimate 55์„ธ ์—ฌ์„ฑ ๊ธฐ์ค€ ๋น„๊ต, ์ง์ „ ํ„ด ๋‚˜์ดยท์„ฑ๋ณ„ ์žฌ์‚ฌ์šฉ
2 4 ์ง€๊ธˆ ์œ ์ง€ ์ค‘์ธ ์„ธ ๊ณ„์•ฝ ํ•ฉ์‚ฐ ์›” ๋ณดํ—˜๋ฃŒ๋Š” ์–ผ๋งˆ์ฏค ๋ผ? ์œค์ง€์€ 55์„ธ ์—ฌ์„ฑ, 3๊ฑด premium_estimate(55, F) 3๊ฑด ๊ฐ๊ฐ ํ˜ธ์ถœ ํ›„ ํ•ฉ์‚ฐ "์กฐํšŒํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค" ๊ธˆ์ง€. 3๊ฑด ํ•ฉ๊ณ„ ์ œ์‹œ
3. ์ตœ์ˆ˜์ง„ ๋ถ€ํ™œ 1 ๊ณ„์•ฝ์ž ์ตœ์ˆ˜์ง„๋‹˜ ๊ณ„์•ฝ ํ˜„ํ™ฉ ์•Œ๋ ค์ค˜ ์—†์Œ customer_contract_lookup(์ด๋ฆ„=์ตœ์ˆ˜์ง„) ์œ ์ง€ 1๊ฑด(์ข…์‹ ) + ํ•ด์ง€ 1๊ฑด(์•”), ํ•ด์ง€์ผ ํ‘œ๊ธฐ
3 2 ํ•ด์ง€๋œ ์•”๋ณดํ—˜ ๋‹ค์‹œ ๋ถ€ํ™œํ•  ์ˆ˜ ์žˆ์–ด? ์กฐ๊ฑด์ด ๋ญ์•ผ? ์ตœ์ˆ˜์ง„ ํ•ด์ง€๋œ ์•”๋ณดํ—˜(ํ•ด์ง€์ผ 2023-12-31) underwriting_reinstatement_rule ๋ถ€ํ™œ ๊ธฐํ•œ(ํ•ด์ง€์ผ+3๋…„), ์—ฐ์ฒด๋ณดํ—˜๋ฃŒยท๋ฉด์ฑ… ์žฌ์ ์šฉ ๋“ฑ
3 3 ๋ถ€ํ™œ์ด ์–ด๋ ค์šฐ๋ฉด 60์„ธ ์—ฌ์„ฑ์ด ์ƒˆ๋กœ ๊ฐ€์ž…ํ•  ์ˆ˜ ์žˆ๋Š” ์•”๋ณดํ—˜ ์žˆ์–ด? ์ตœ์ˆ˜์ง„ 60์„ธ ์—ฌ์„ฑ product_search(์•”) + ๊ฐ€์ž… ์กฐ๊ฑด 60์„ธ ์—ฌ์„ฑ ๊ธฐ์ค€, ์ง์ „ ๋งฅ๋ฝ ๋‚˜์ดยท์„ฑ๋ณ„ ์‚ฌ์šฉ
3 4 ์œ ์ง€ ์ค‘์ธ ๊ฐ„ํŽธ๊ณ ์ง€์ข…์‹ ๋ณดํ—˜ ๋ณด์žฅ ๋‚ด์šฉ ์ž์„ธํžˆ ์•Œ๋ ค์ค˜ ์ตœ์ˆ˜์ง„ ์œ ์ง€ 1๊ฑด ์ข…์‹  coverage_detail ์ง์ „ ์กฐํšŒํ•œ ์ข…์‹ ๋ณดํ—˜ ๋ณด์žฅ ์ƒ์„ธ(์‚ฌ๋ง๋ณดํ—˜๊ธˆยท๊ฐ์•กยทํ•ด์•ฝํ™˜๊ธ‰๊ธˆ)
4. ํƒ์‹œ๊ธฐ์‚ฌ+๊ณ ํ˜ˆ์•• 1 48์„ธ ๋‚จ์„ฑ์ธ๋ฐ ํƒ์‹œ๊ธฐ์‚ฌ์•ผ. ๊ณ ํ˜ˆ์•• ์•ฝ ๋ณต์šฉ ์ค‘์ด๊ณ  ์•”๋ณดํ—˜ ๊ฐ€์ž…ํ•˜๊ณ  ์‹ถ๋Œ€ ์—†์Œ ์ง์—…ยท์œ ๋ณ‘๋ ฅ ํŒŒ์•… ๋ณตํ•ฉ ์งˆ๋ฌธ ์ธ์‹, ๋‹จ๊ณ„๋ณ„ ๋‹ต๋ณ€ ๊ฐ€๋Šฅ ์•ˆ๋‚ด
4 2 ํƒ์‹œ๊ธฐ์‚ฌ๋ฉด ์ง์—… ์œ„ํ—˜๋“ฑ๊ธ‰ ๋•Œ๋ฌธ์— ๋ณดํ—˜๋ฃŒ๊ฐ€ ๋” ๋น„์‹ธ์ง€๊ฑฐ๋‚˜ ๊ฑฐ์ ˆ๋  ์ˆ˜ ์žˆ์–ด? 48์„ธ ๋‚จ์„ฑ, ํƒ์‹œ๊ธฐ์‚ฌ underwriting_high_risk_job_check ํ• ์ฆ ์ง๊ตฐ ํ™•์ธ, ๋ณดํ—˜๋ฃŒ ์˜ํ–ฅ ์•ˆ๋‚ด
4 3 ์ฒซ๋‚ ๋ถ€ํ„ฐ์•”๋ณดํ—˜์€ ๊ฐ€์ž… ์กฐ๊ฑด์ด๋ž‘ ๋ณด์žฅ์ด ์–ด๋–ป๊ฒŒ ๋ผ? ์ง์—… ๋“ฑ๊ธ‰ + ๊ณ ํ˜ˆ์•• product_search, coverage_detail ์ฒซ๋‚ ๋ถ€ํ„ฐ์•”๋ณดํ—˜ ๊ฐ€์ž…์กฐ๊ฑดยท๋ณด์žฅ, ๊ณ ํ˜ˆ์••ยทํ• ์ฆ ๋งฅ๋ฝ ์œ ์ง€
4 4 ๊ฐ„ํŽธ์‹ฌ์‚ฌ๋กœ ๊ฐ€์ž…ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฑด๊ฐ•๋ณดํ—˜๋„ ์žˆ์–ด? 48์„ธ ๋‚จ์„ฑ, ๊ณ ํ˜ˆ์••, ํƒ์‹œ๊ธฐ์‚ฌ product_search(๊ฐ„ํŽธ์‹ฌ์‚ฌ ๊ฑด๊ฐ•) ๊ฐ„ํŽธ์‹ฌ์‚ฌ ์ƒํ’ˆ ์ถ”์ฒœ, ์ง์ „ ๋งฅ๋ฝ(์ง์—…ยท๋ณ‘๋ ฅ) ์œ ์ง€
5. ์‹œ๋‹ˆ์–ด ์ข…ํ•ฉ 1 70์„ธ ์•„๋ฒ„์ง€์ธ๋ฐ ์‚ฌ๋ง๋ณด์žฅ์ด๋ž‘ ์น˜์•„๋ณดํ—˜ ๋‘˜ ๋‹ค ์•Œ์•„๋ณด๊ณ  ์‹ถ๋Œ€ ์—†์Œ product_search(์‚ฌ๋งยท์น˜์•„) 70์„ธ ๊ฐ€๋Šฅ ์ƒํ’ˆ ์ถ”์ฒœ, '์•„๋ฒ„์ง€'=๋‚จ์„ฑ ๋งฅ๋ฝ
5 2 ๊ฑด๊ฐ•ํ•ด์ง€๋Š”์ข…์‹ ๋ณดํ—˜๋„ 70์„ธ์— ๊ฐ€์ž… ๊ฐ€๋Šฅํ•ด? ๋ณด์žฅ ๋‚ด์šฉ์ด๋ž‘ ์—ฐ๊ธˆ์ „ํ™˜ ์กฐ๊ฑด ์•Œ๋ ค์ค˜ 70์„ธ, ์ง์ „ ์ƒํ’ˆ ๋งฅ๋ฝ coverage_summary 70์„ธ ๊ฐ€์ž… ๊ฐ€๋Šฅ ํ™•์ธ, ๋ณด์žฅยท์—ฐ๊ธˆ์ „ํ™˜ ์กฐ๊ฑด
5 3 ๋“ ๋“ ํ•œ์‹ค๋ฒ„์น˜์•„๋ณดํ—˜์€ 70์„ธ์— ๋ณด์žฅ ๋ฒ”์œ„๊ฐ€ ์–ด๋–ป๊ฒŒ ๋ผ? 70์„ธ coverage_summary 70์„ธ ๋ณด์žฅ๋ฒ”์œ„(์ถฉ์ „ยทํฌ๋ผ์šด), ์ง์ „ ๋‚˜์ด ์žฌ์‚ฌ์šฉ
5 4 ๋ฐฉ๊ธˆ ์–˜๊ธฐํ•œ ๋‘ ์ƒํ’ˆ ๋‹ค ๊ฐ€์ž…ํ•˜๋ฉด ์›” ๋ณดํ—˜๋ฃŒ ํ•ฉ์ณ์„œ ์–ผ๋งˆ์ฏค ๋‚˜์™€? 70์„ธ ๋‚จ์„ฑ(์•„๋ฒ„์ง€), ์ง์ „ ๋‘ ์ƒํ’ˆ(์ข…์‹ ยท์‹ค๋ฒ„์น˜์•„) premium_estimate(70, M) 2ํšŒ ํ˜ธ์ถœ ํ›„ ํ•ฉ์‚ฐ ์ง์ „ ๋งฅ๋ฝ ์‚ฌ์šฉ. ์•„๋ฒ„์ง€โ†’๋‚จ์„ฑ ์ž๋™ ์ธ์‹. "์„ฑ๋ณ„ ํ•„์š”" ๋ฐ˜๋ณต ๊ธˆ์ง€

๊ณตํ†ต ๊ฒ€์ฆ:

  • ๋งค ํ„ด ๋‹ต๋ณ€์ด ์ง์ „ ์ฑ—๋ด‡ ์‘๋‹ตยท์ด์ „ ํ„ด ์‚ฌ์šฉ์ž ์ž…๋ ฅ์„ ์ฐธ์กฐํ–ˆ๋Š”์ง€(์žฌ์š”์ฒญยท๋ฌด์‹œ ์—†์ด) ํ™•์ธ
  • ๊ณ„์•ฝ์ž IDยท์ด๋ฆ„์„ ์ด๋ฏธ ์กฐํšŒํ•œ ๋Œ€ํ™”์—์„œ๋Š” ๊ฐ™์€ ์ •๋ณด๋ฅผ ๋‹ค์‹œ ์š”๊ตฌํ•˜์ง€ ๋ง๊ณ , ํ•„์š”ํ•œ ์ถ”๊ฐ€ ์ธ์ž(๋‚˜์ดยท์„ฑ๋ณ„ ๋“ฑ)๋งŒ ์ด์ „ ๋งฅ๋ฝ์—์„œ ์ฑ„์›Œ์„œ ๋„๊ตฌ ํ˜ธ์ถœ

6. ๊ตฌํ˜„ ์ƒ์„ธ

6-1. LangGraph 5๋…ธ๋“œ ํŒŒ์ดํ”„๋ผ์ธ

START โ†’ [input_guardrail] โ†’ [query_rewriter] โ†’ [agent โ†” tools] โ†’ [output_guardrail] โ†’ END
๋…ธ๋“œ ์—ญํ•  ์†Œ์š” ์‹œ๊ฐ„
input_guardrail ์ •๊ทœ์‹(L1) + ์ž„๋ฒ ๋”ฉ(L2)์œผ๋กœ ์ด์ƒ ์š”์ฒญ ์ฐจ๋‹จ <5ms
query_rewriter "๊ทธ๊ฑฐ ์–ผ๋งˆ์•ผ?" ๊ฐ™์€ ํ›„์†์งˆ๋ฌธ์„ ์ด์ „ ๋งฅ๋ฝ์œผ๋กœ ์žฌ์ž‘์„ฑ 0~1s
agent ChromaDB Top-K ๊ฒ€์ƒ‰ โ†’ LLM ๋„๊ตฌ ํ˜ธ์ถœ 1~5s
tools ToolRegistry ๋™์  ๋””์ŠคํŒจ์น˜ โ†’ ๋„๊ตฌ ์‹คํ–‰ 10~100ms
output_guardrail PIIยท๊ธˆ์น™์–ดยท์ƒํ’ˆ์ฝ”๋“œยท๋„๊ตฌ๋ช… ์ œ๊ฑฐ + ๋ฉด์ฑ… ๋ฌธ๊ตฌ ์ž๋™ ์ถ”๊ฐ€ <2ms

์ฟผ๋ฆฌ ์žฌ์ž‘์„ฑ์€ Advanced RAG ํ•ต์‹ฌ ๊ธฐ๋ฒ•์ธ Query Transformation์— ํ•ด๋‹นํ•จ (์ฐธ๊ณ ).

6-2. ์ƒํ’ˆ๊ณต์‹œ์‹ค PDF RAG

๋ณดํ—˜ ์ƒํ’ˆ๊ณต์‹œ์‹ค์—์„œ 12๊ฐœ ์ƒํ’ˆ์š”์•ฝ์„œ + ํ‘œ์ค€์•ฝ๊ด€ + ํšŒ์‚ฌ ์ •๋ณด๋ฅผ ์ˆ˜์ง‘ํ•จ. PyMuPDF๋กœ ํ…์ŠคํŠธ ์ถ”์ถœ โ†’ 500์ž ์ฒญํฌ โ†’ ChromaDB ์ธ์ œ์ŠคํŠธ(~1,400 ๋ฒกํ„ฐ). ๋„๊ตฌ ๋ฐ์ดํ„ฐ์— ์—†๋Š” ์•ฝ๊ด€ ์กฐํ•ญยท๋ฉด์ฑ… ๊ทœ์ •์„ RAG๊ฐ€ ๋ณด์™„ํ•จ.

6-3. LLM ์—ฐ๋™

ํ•ญ๋ชฉ ์„ค๋ช…
์‹œ์Šคํ…œ ํ”„๋กฌํ”„ํŠธ 12๊ฐœ ์ƒํ’ˆ ๋ชฉ๋ก์ด PRODUCTS ๋”•์…”๋„ˆ๋ฆฌ์—์„œ ๋™์  ๋ฐ˜์˜๋จ. ๋„๊ตฌ ์ฒด์ด๋‹ ๊ทœ์น™๋„ ํฌํ•จ
์‚ฌ๊ณ ๊ณผ์ • ํ•„ํ„ฐ๋ง Qwen3 <think> ๋ธ”๋ก์„ ์ŠคํŠธ๋ฆฌ๋ฐ ์ค‘ ์‹ค์‹œ๊ฐ„ ํ•„ํ„ฐ๋ง. ์‚ฌ์šฉ์ž์—๊ฒŒ ์ตœ์ข… ๋‹ต๋ณ€๋งŒ ๋…ธ์ถœ
๋„๊ตฌ ๋ ˆ๋ฒจ ๊ฐ€๋“œ ๋‚˜์ด/์„ฑ๋ณ„ ๋“ฑ ํ•„์ˆ˜๊ฐ’ ๋ฏธ์ œ๊ณต ์‹œ needs_user_input ๋ฐ˜ํ™˜ โ†’ LLM์ด ๋˜๋ฌป๋Š” ๊ตฌ์กฐ

6-4. ์„œ๋น™

๋ฐฉ์‹ ์„ค๋ช… ๋Œ€์ƒ
FastAPI (REST/SSE) ์›น Chat UI + REST API + Admin Dashboard ์ผ๋ฐ˜ ์‚ฌ์šฉ์žยท์šด์˜์ž
MCP Server (SSE/stdio) ๋„๊ตฌ 54 + ๋ฆฌ์†Œ์Šค 17 + ํ”„๋กฌํ”„ํŠธ 8 ๋…ธ์ถœ Claude Desktop, Cursor ๋“ฑ

7. ์šด์˜

7-1. ๋„๊ตฌ ์ถ”๊ฐ€ ์ฒดํฌ๋ฆฌ์ŠคํŠธ

์ƒˆ ๋„๊ตฌ๋ฅผ ์ถ”๊ฐ€ํ•  ๋•Œ ์•„๋ž˜ ์ˆœ์„œ๋ฅผ ๋”ฐ๋ฆ„.

โ‘  ๋„๊ตฌ ํ•จ์ˆ˜ ์ž‘์„ฑ โ€” app/tools/ ์•„๋ž˜ ํ•ด๋‹น ๋ชจ๋“ˆ์— @tool ํ•จ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•จ. tool.name์ด ์ดํ›„ ๋ชจ๋“  ์—ฐ๋™์˜ ํ‚ค๊ฐ€ ๋จ.

โ‘ก ToolCard ๋“ฑ๋ก โ€” app/tool_search/tool_cards.py์˜ _CARDS ๋ฆฌ์ŠคํŠธ์— ์นด๋“œ๋ฅผ ์ถ”๊ฐ€ํ•จ.

ํ•„๋“œ ๊ทœ์น™
name tool.name๊ณผ ์ •ํ™•ํžˆ ์ผ์น˜ํ•ด์•ผ ํ•จ
purpose ํ•œ ๋ฌธ์žฅ์œผ๋กœ ๋„๊ตฌ ๊ธฐ๋Šฅ์„ ์„ค๋ช…
when_to_use ์‹ค์ œ ์‚ฌ์šฉ์ž ๋ฐœํ™” ํŒจํ„ด์œผ๋กœ ์ž‘์„ฑ
when_not_to_use ํ˜ผ๋™ ๋„๊ตฌ๋ฅผ โ†’ tool_name ์‚ฌ์šฉ ํ˜•์‹์œผ๋กœ ๋ช…์‹œ
tags ๋„๋ฉ”์ธ ํ‚ค์›Œ๋“œ (ํ•„ํ„ฐ๋ง์šฉ)

โ‘ข ํ˜ผ๋™ ์Œ ๊ด€๋ฆฌ โ€” ๊ธฐ๋Šฅ์ด ์œ ์‚ฌํ•œ ๋„๊ตฌ๊ฐ€ ์žˆ์œผ๋ฉด ์–‘๋ฐฉํ–ฅ์œผ๋กœ when_not_to_use์™€ CONFUSION_PAIRS์— ๋“ฑ๋กํ•จ.

โ‘ฃ ๊ฒ€์ฆ โ€” python -m scripts.eval_tool_recall --compare๋กœ Recall@k ํ™•์ธ.

์—ฐ๋™ ์ง€์  ์ž๋™/์ˆ˜๋™ ๋น„๊ณ 
ChromaDB ์ž„๋ฒ ๋”ฉ ์ž๋™ ์„œ๋ฒ„ ์‹œ์ž‘ ์‹œ ํ•ด์‹œ ๋น„๊ต โ†’ ๋ณ€๊ฒฝ๋ถ„๋งŒ ์žฌ์ธ๋ฑ์‹ฑ
LLM tool description ์ž๋™ when_not_to_use๊ฐ€ description์— ์ž๋™ ์ฃผ์ž…
๋„๊ตฌ ํ•จ์ˆ˜ ์ˆ˜๋™ ์นด๋“œ๋งŒ ์žˆ๊ณ  ํ•จ์ˆ˜๊ฐ€ ์—†์œผ๋ฉด ๋™์ž‘ํ•˜์ง€ ์•Š์Œ
CONFUSION_PAIRS ์ˆ˜๋™ ์œ ์‚ฌ ๋„๊ตฌ ์กด์žฌ ์‹œ ๋ฐ˜๋“œ์‹œ ๋“ฑ๋ก

7-2. Admin Dashboard

CLI ๋Œ€์‹  ๋ธŒ๋ผ์šฐ์ €(/admin/tools)์—์„œ ๋„๊ตฌ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์›น UI์ž„.

๊ธฐ๋Šฅ ์„ค๋ช…
๋Œ€์‹œ๋ณด๋“œ ๋„๊ตฌ ์ˆ˜, ChromaDB ๋ฒกํ„ฐ ์ˆ˜, Registry ๋ฒ„์ „, ์ƒํƒœ ๋ชจ๋‹ˆํ„ฐ๋ง
ToolCard ํŽธ์ง‘ purpose, when_to_use, when_not_to_use, tags ์ˆ˜์ • โ†’ ์ฆ‰์‹œ ๋ฐ˜์˜
๋ฒ„์ „ ์ด๋ ฅ ๋ณ€๊ฒฝ ์ด๋ ฅ ์กฐํšŒ, Diff ๋น„๊ต, ํŠน์ • ๋ฒ„์ „์œผ๋กœ ๋กค๋ฐฑ
ํ€ต ํ…Œ์ŠคํŠธ ์‹ค์‹œ๊ฐ„ ์ฟผ๋ฆฌ ๊ฒ€์ƒ‰, ๋ฐฐ์น˜ Recall ํ‰๊ฐ€, LLM ์‹คํŒจ ๋ถ„์„
๋„๊ตฌ ํ•ด์ œ ํ™•์ธ ๋ชจ๋‹ฌ โ†’ DELETE โ†’ ChromaDB ๋ฒกํ„ฐ ์ฆ‰์‹œ ์‚ญ์ œ
๋ชจ๋“ˆ ํ•ซ๋ฆฌ๋กœ๋“œ 8๊ฐœ ๋ชจ๋“ˆ ์„ ํƒ โ†’ ์ฝ”๋“œ ๋ณ€๊ฒฝ๋ถ„ ์„œ๋ฒ„ ์žฌ์‹œ์ž‘ ์—†์ด ๋ฐ˜์˜

ํ€ต ํ…Œ์ŠคํŠธ ํƒญ์—์„œ ์ˆ˜์ • ์ „ํ›„ Recall@k๋ฅผ ๋น„๊ตํ•˜๊ณ , ์‹คํŒจ ์ฟผ๋ฆฌ์— ๋Œ€ํ•ด LLM์ด ToolCard ๊ฐœ์„ ์•ˆ์„ ์ œ์•ˆํ•˜๋ฏ€๋กœ ์ฝ”๋“œ ๋ณ€๊ฒฝ ์—†์ด ๊ฒ€์ƒ‰ ์ •ํ™•๋„๋ฅผ ํŠœ๋‹ํ•  ์ˆ˜ ์žˆ์Œ.

7-3. ๋Ÿฐํƒ€์ž„ API

curl http://localhost:8080/api/tools                              # ์ „์ฒด ๋„๊ตฌ ๋ชฉ๋ก
curl -X DELETE http://localhost:8080/api/tools/premium_estimate    # ๋„๊ตฌ ํ•ด์ œ
curl -X POST http://localhost:8080/api/tools/reload-module/premium # ๋ชจ๋“ˆ ํ•ซ๋ฆฌ๋กœ๋“œ

8. ๊ธฐ์ˆ  ์„ ํƒ ๊ทผ๊ฑฐ

8-1. ๋ฒกํ„ฐ DB โ€” 8๊ฐœ ํ›„๋ณด ๋น„๊ต ํ›„ ChromaDB ์„ ํƒ

์ด ํ”„๋กœ์ ํŠธ๋Š” ๋ฌด๋ฃŒ ์˜คํ”ˆ์†Œ์Šค๋งŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๊ณ , HF Spaces Docker ๋‹จ์ผ ์ปจํ…Œ์ด๋„ˆ ๋ฐฐํฌ๊ฐ€ ํ•„์ˆ˜ ์กฐ๊ฑด์ž„. ์ด ์กฐ๊ฑด์œผ๋กœ 8๊ฐœ ๋ฒกํ„ฐ DB๋ฅผ ๋น„๊ตยทํ•„ํ„ฐ๋งํ•จ.

Step 1. ์œ ๋ฃŒ/ํด๋ผ์šฐ๋“œ ์ „์šฉ ์ œ์™ธ

DB ์ œ์™ธ ์‚ฌ์œ 
Pinecone ์™„์ „ ๊ด€๋ฆฌํ˜•(SaaS ์ „์šฉ), ์ž์ฒด ํ˜ธ์ŠคํŒ… ๋ถˆ๊ฐ€. ํ”„๋กœ๋•์…˜ $50/์›” ์ตœ์†Œ ๊ณผ๊ธˆ (Pinecone Pricing)
MongoDB Atlas Search ๋ฒกํ„ฐ ๊ฒ€์ƒ‰์€ Atlas ํด๋ผ์šฐ๋“œ ์ „์šฉ. ์—ฐ๊ฐ„ $5,000~$70,000 (Firecrawl). ๋กœ์ปฌ MongoDB CE์—๋Š” ๋ฒกํ„ฐ ๊ฒ€์ƒ‰ ๋ฏธ์ง€์›

Step 2. ์˜คํ”ˆ์†Œ์Šค์ด๋‚˜ ์ธํ”„๋ผ ๊ณผ์ž‰์ธ ํ›„๋ณด ์ œ์™ธ

DB ๋ผ์ด์„ ์Šค ์ œ์™ธ ์‚ฌ์œ 
Milvus Apache 2.0 ํ”„๋กœ๋•์…˜ ๋ถ„์‚ฐ ๋ชจ๋“œ์— K8s ํ•„์ˆ˜. Standalone ๊ฐ€๋Šฅํ•˜๋‚˜ etcd+MinIO ์˜์กด์„ฑ. ~1,800 ๋ฒกํ„ฐ์— ์˜ค๋ฒ„์—”์ง€๋‹ˆ์–ด๋ง (dev.to)
OpenSearch Apache 2.0 JVM ๊ธฐ๋ฐ˜ ๊ฒ€์ƒ‰ ์—”์ง„. ๋ฉ”๋ชจ๋ฆฌ 1GB+ ํ•„์š”, Docker ๋‚ด Java ํ”„๋กœ์„ธ์Šค ์ถ”๊ฐ€ ๋ถ€๋‹ด. ๋ฒกํ„ฐ ๊ฒ€์ƒ‰์€ knn_vector ํ•„๋“œ๋กœ ์ง€์›ํ•˜๋‚˜, ๊ฒ€์ƒ‰ ์—”์ง„ ์ˆ˜์ค€ ์šด์˜ ๋ณต์žก๋„ (Firecrawl)
Redis Stack SSPL / RSALv2 2024๋…„๋ถ€ํ„ฐ Redis ๋ผ์ด์„ ์Šค๊ฐ€ SSPL๋กœ ๋ณ€๊ฒฝ๋˜์–ด ์ˆœ์ˆ˜ ์˜คํ”ˆ์†Œ์Šค๊ฐ€ ์•„๋‹˜. ๋ฒกํ„ฐ ๊ฒ€์ƒ‰์€ RediSearch ๋ชจ๋“ˆ์— ์˜์กด. ๋ณ„๋„ Redis ์„œ๋ฒ„ ํ”„๋กœ์„ธ์Šค ํ•„์š” (Redis Blog)

Step 3. ์ตœ์ข… ํ›„๋ณด โ€” ChromaDB vs pgvector

๊ธฐ์ค€ ChromaDB PostgreSQL + pgvector
๋ผ์ด์„ ์Šค Apache 2.0 PostgreSQL License
์„ค์น˜ pip install chromadb PostgreSQL ์„œ๋ฒ„ + CREATE EXTENSION vector
์•„ํ‚คํ…์ฒ˜ ์ž„๋ฒ ๋””๋“œ (in-process) ๋ณ„๋„ DB ์„œ๋ฒ„ ํ”„๋กœ์„ธ์Šค
Docker ๋ฐฐํฌ ์ถ”๊ฐ€ ํ”„๋กœ์„ธ์Šค ์—†์Œ PostgreSQL ๋ฐ๋ชฌ ํ•„์š”
๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ํ•„ํ„ฐ๋ง O (where ์ ˆ) O (SQL WHERE)
์‹ค์‹œ๊ฐ„ upsert O O
์˜์†์„ฑ O (SQLite + parquet) O
ํ•œ๊ตญ์–ด ์ปค์Šคํ…€ ์ž„๋ฒ ๋”ฉ ์ง์ ‘ ์ „๋‹ฌ ๊ฐ€๋Šฅ ์ง์ ‘ ์ „๋‹ฌ ๊ฐ€๋Šฅ
์šด์˜ ๋ณต์žก๋„ ์ตœ์†Œ (ํŒŒ์ผ ๊ธฐ๋ฐ˜) ์ค‘๊ฐ„ (DB ๊ด€๋ฆฌ ํ•„์š”)

ChromaDB๋ฅผ ์„ ํƒํ•œ ์ด์œ :

  1. Docker ๋‹จ์ผ ์ปจํ…Œ์ด๋„ˆ ์ ํ•ฉ์„ฑ โ€” HF Spaces๋Š” ํ•˜๋‚˜์˜ Docker ์ปจํ…Œ์ด๋„ˆ๋กœ ์„œ๋น™ํ•จ. ChromaDB๋Š” ์ž„๋ฒ ๋””๋“œ ๋ชจ๋“œ๋กœ FastAPI ํ”„๋กœ์„ธ์Šค ์•ˆ์—์„œ ๋™์ž‘ํ•˜๋ฏ€๋กœ ๋ณ„๋„ DB ํ”„๋กœ์„ธ์Šค๊ฐ€ ํ•„์š” ์—†์Œ. pgvector๋Š” PostgreSQL ๋ฐ๋ชฌ์„ ํ•จ๊ป˜ ๋„์›Œ์•ผ ํ•จ.

  2. ์ธํ”„๋ผ ์ œ๋กœ โ€” pip install chromadb ํ•œ ์ค„๋กœ ๋๋‚จ. DB ์„ค์ •, ์Šคํ‚ค๋งˆ ์ƒ์„ฑ, ์ปค๋„ฅ์…˜ ํ’€ ๊ด€๋ฆฌ๊ฐ€ ์—†์Œ.

  3. ์‹ค์‹œ๊ฐ„ upsert โ€” ToolCard ์ˆ˜์ • ์‹œ ์„œ๋ฒ„ ์žฌ์‹œ์ž‘ ์—†์ด ์ฆ‰์‹œ ๋ฒกํ„ฐ๋ฅผ ๊ฐฑ์‹ ํ•ด์•ผ ํ•จ. ChromaDB๋Š” collection.upsert()๋กœ ํ•ด๊ฒฐ๋จ. FAISS๋Š” ์ธ๋ฑ์Šค ์ „์ฒด๋ฅผ rebuild ํ•ด์•ผ ํ•จ.

  4. ๊ทœ๋ชจ ์ ํ•ฉ์„ฑ โ€” ๋„๊ตฌ 54๊ฐœ ร— ํ•„๋“œ 7๊ฐœ = ~1,800 ๋ฒกํ„ฐ. 10M ๋ฒกํ„ฐ ๋ฏธ๋งŒ ํ”„๋กœํ† ํƒ€์ž…์—์„œ ChromaDB ๊ถŒ์žฅ (Firecrawl) (dev.to).

  5. LangChain ์ƒํƒœ๊ณ„ ํ†ตํ•ฉ โ€” LangGraph/LangChain๊ณผ ๋„ค์ดํ‹ฐ๋ธŒ ์—ฐ๋™์ด ๊ฒ€์ฆ๋˜์–ด ์žˆ์Œ (TrueFoundry).

์Šค์ผ€์ผ ์•„์›ƒ ์‹œ๋‚˜๋ฆฌ์˜ค: ๋ฒกํ„ฐ๊ฐ€ 10M์„ ๋„˜๊ฑฐ๋‚˜ ๋ฉ€ํ‹ฐ๋…ธ๋“œ HA๊ฐ€ ํ•„์š”ํ•ด์ง€๋ฉด Qdrant(Rust ๊ธฐ๋ฐ˜, ๊ณ ์„ฑ๋Šฅ ํ•„ํ„ฐ๋ง) ๋˜๋Š” Milvus(K8s ๋ถ„์‚ฐ)๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์  ๊ฒฝ๋กœ์ž„ (Firecrawl).

8-2. ์ž„๋ฒ ๋”ฉ ๋ชจ๋ธ โ€” multilingual-e5-large

๊ธฐ์ค€ e5-base e5-large OpenAI ada-002
Kor-IR NDCG@10 โ€” 80.35 (OSS ์ตœ์ƒ์œ„) โ€”
Mr. TyDi ํ•œ๊ตญ์–ด MRR@10 55.8 61.6 (+10%) โ€”
๋น„์šฉ ๋ฌด๋ฃŒ ๋กœ์ปฌ ๋ฌด๋ฃŒ ๋กœ์ปฌ $0.13/1M tokens
์ถ”๋ก  ์†๋„ ~5ms ~10ms ๋„คํŠธ์›Œํฌ ์˜์กด

Kor-IR ๋ฒค์น˜๋งˆํฌ ์˜คํ”ˆ์†Œ์Šค ์ตœ์ƒ์œ„. ๋น„๋Œ€์นญ ๊ฒ€์ƒ‰ ์‹œ "query: " / "passage: " ํ”„๋ฆฌํ”ฝ์Šค ํ•„์ˆ˜ (๋…ผ๋ฌธ). ๋กœ์ปฌ ์ถ”๋ก (~10ms/์ฟผ๋ฆฌ)์œผ๋กœ ์™ธ๋ถ€ API์— ์˜์กดํ•˜์ง€ ์•Š์Œ (๋ชจ๋ธ ์นด๋“œ).

8-3. Tool Card ํ•™์ˆ  ๊ทผ๊ฑฐ

์ถœ์ฒ˜ ํ•ต์‹ฌ ๊ธฐ์—ฌ
Tool-DE (Lu et al., 2025) ๋„๊ตฌ ๋ฌธ์„œ ํ™•์žฅ์œผ๋กœ NDCG@10 +6~7ppt, Recall@10 +10ppt
Re-Invoke (Google, EMNLP 2024) ํ•ฉ์„ฑ ์ฟผ๋ฆฌ ์ƒ์„ฑ์œผ๋กœ nDCG@5 ์œ ์˜๋ฏธ ํ–ฅ์ƒ
ToolBench (ICLR 2024) ๋„๊ตฌ ์ˆ˜ ์ฆ๊ฐ€ ์‹œ cross-reference๊ฐ€ ์ •ํ™•๋„ ์ €ํ•˜๋ฅผ ๋ฐฉ์ง€
RAG-MCP (WRITER, 2025) ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ๊ธฐ๋ฐ˜ ์ธ๋ฑ์‹ฑ โ†’ ํ† ํฐ 50%+ ์ ˆ๊ฐ

9. ์•Œ๋ ค์ง„ ํ•œ๊ณ„ ๋ฐ ๊ณ ๋„ํ™” ๋ฐฉํ–ฅ

ํ•œ๊ณ„ ํ˜„์ƒ ๋ฐฉํ–ฅ
when_to_use ์˜ค๋ฒ„ํ• product_search์— ํƒ€ ๋„๊ตฌ ์˜์—ญ ๋ฐœํ™”๊ฐ€ ์ž„๋ฒ ๋”ฉ์„ ํฌ์„ํ•จ ์ˆœ์ˆ˜ ์ƒํ’ˆ ๊ฒ€์ƒ‰ ๋ฐœํ™”๋งŒ ์œ ์ง€
cross-reference ๋ˆ„๋ฝ renewal_projection โ†” renewal_notice ์–‘๋ฐฉํ–ฅ ๊ฐ€์ด๋“œ ๋ถ€์žฌ when_not_to_use ์–‘๋ฐฉํ–ฅ ๋ณด์™„
์ˆ˜๋™ ์ž‘์„ฑ ํ•œ๊ณ„ 54๊ฐœ ร— ~7๊ฐœ = ~380๊ฐœ when_to_use๋ฅผ ์ˆ˜๋™ ๊ด€๋ฆฌ ์ค‘ Re-Invoke ๋ฐฉ์‹ LLM ํ•ฉ์„ฑ ์ฟผ๋ฆฌ ์ž๋™ ์ƒ์„ฑ
์ •์  no-call ์ž„๊ณ„๊ฐ’ tool-call min(0.867)๊ณผ no-call max(0.877)์ด ๊ฒน์นจ Reranker 2๋‹จ๊ณ„ ๋„์ž…

Quick Start

# 1. ์„ค์น˜
python -m venv .venv && source .venv/bin/activate
pip install -e .

# 2. ํ™˜๊ฒฝ๋ณ€์ˆ˜ (.env)
OPENROUTER_API_KEY=sk-or-v1-your-key
OPENROUTER_MODEL=qwen/qwen3-14b
EMBEDDING_MODEL=intfloat/multilingual-e5-large

# 3. ChromaDB ์ดˆ๊ธฐํ™” (์ตœ์ดˆ 1ํšŒ)
python scripts/init_vectordb.py

# 4. ์„œ๋ฒ„ ์‹คํ–‰
python run.py                         # FastAPI โ†’ http://localhost:8080
python run_mcp.py                     # MCP Server
python run_mcp.py --inspect           # MCP Inspector UI

# 5. ๋„๊ตฌ ๋ผ์šฐํŒ… ํ‰๊ฐ€
python -m scripts.eval_tool_recall --compare

ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ

app/
โ”œโ”€โ”€ main.py                 # FastAPI (REST/SSE + think ํ•„ํ„ฐ๋ง)
โ”œโ”€โ”€ config.py               # Settings + ์ž„๋ฒ ๋”ฉ ๋ชจ๋ธ ์‹ฑ๊ธ€ํ†ค
โ”œโ”€โ”€ graph/                  # LangGraph 5๋…ธ๋“œ ํŒŒ์ดํ”„๋ผ์ธ
โ”‚   โ”œโ”€โ”€ builder.py          #   ๊ทธ๋ž˜ํ”„ ๋นŒ๋“œ + ๋™์  ๋„๊ตฌ ๋””์ŠคํŒจ์น˜
โ”‚   โ”œโ”€โ”€ nodes.py            #   agent ๋…ธ๋“œ (ChromaDB ๋ผ์šฐํŒ… + LLM)
โ”‚   โ”œโ”€โ”€ guardrails.py       #   ์ž…๋ ฅ(L1+L2) / ์ถœ๋ ฅ ๊ฐ€๋“œ๋ ˆ์ผ
โ”‚   โ””โ”€โ”€ query_rewrite.py    #   ํ›„์†์งˆ๋ฌธ ์žฌ์ž‘์„ฑ
โ”œโ”€โ”€ tools/ (54๊ฐœ, 8๋ชจ๋“ˆ)    # product / premium / coverage / underwriting
โ”‚   โ”œโ”€โ”€ __init__.py         #   ToolRegistry (ํ•ซ๋ฆฌ๋กœ๋“œ)
โ”‚   โ””โ”€โ”€ data.py             #   12๊ฐœ ์ƒํ’ˆ ๋ฐ์ดํ„ฐ + ์‹œ์Šคํ…œ ํ”„๋กฌํ”„ํŠธ
โ”œโ”€โ”€ tool_search/            # ChromaDB ๋ฉ€ํ‹ฐ๋ฒกํ„ฐ ๋ผ์šฐํŒ…
โ”‚   โ”œโ”€โ”€ embedder.py         #   ์ž„๋ฒ ๋”ฉ + Top-K ๊ฒ€์ƒ‰
โ”‚   โ”œโ”€โ”€ tool_cards.py       #   54๊ฐœ ToolCard
โ”‚   โ””โ”€โ”€ toolcard_store.py   #   ToolCard JSON ์˜์†ํ™” + ๋ฒ„์ „ ์ด๋ ฅ
โ”œโ”€โ”€ rag/                    # ์ƒํ’ˆ๊ณต์‹œ์‹ค PDF RAG
โ”‚   โ”œโ”€โ”€ retriever.py        #   ์ธ์ œ์ŠคํŠธ + ๊ฒ€์ƒ‰
โ”‚   โ””โ”€โ”€ splitter.py         #   ํ•œ๊ตญ์–ด ๋ฌธ์žฅ๊ฒฝ๊ณ„ ์ฒญํฌ ๋ถ„ํ• 
โ””โ”€โ”€ mcp_server/             # MCP ํ”„๋กœํ† ์ฝœ ์„œ๋ฒ„ + Inspector

templates/
โ”œโ”€โ”€ index.html              # ์ฑ—๋ด‡ Chat UI (์ƒํ’ˆ ์นดํƒˆ๋กœ๊ทธ, ์‹œ๋‚˜๋ฆฌ์˜ค)
โ””โ”€โ”€ admin_tools.html        # Tool Admin Dashboard

scripts/
โ”œโ”€โ”€ init_vectordb.py        # ChromaDB ์ดˆ๊ธฐํ™”
โ””โ”€โ”€ eval_tool_recall.py     # Recall@k / MRR ํ‰๊ฐ€

๋„๊ตฌ ์นดํƒˆ๋กœ๊ทธ (54๊ฐœ)

๋ชจ๋“ˆ ์ˆ˜ ์ฃผ์š” ๊ธฐ๋Šฅ
product 10 ์ƒํ’ˆ ๊ฒ€์ƒ‰/์กฐํšŒ/๋น„๊ต, ํŠน์•ฝ, FAQ
premium 8 ๋ณดํ—˜๋ฃŒ ์‚ฐ์ถœ/๋น„๊ต, ํ”Œ๋žœ, ๊ฐฑ์‹  ์ถ”์ •
coverage 9 ๋ณด์žฅ ์š”์•ฝ/์ƒ์„ธ, ๊ธ‰๋ถ€ ๊ธˆ์•ก
underwriting 12 ๊ฐ€์ž… ์‹ฌ์‚ฌ, ๋…น์•„์›ƒ ๋ฃฐ, ์ง์—… ์œ„ํ—˜๋„
compliance 6 ์ค€๋ฒ• ๋ฉ˜ํŠธ, ๊ธˆ์น™์–ด, PII ๋งˆ์Šคํ‚น
claims 4 ์ฒญ๊ตฌ ์ ˆ์ฐจ, ์„œ๋ฅ˜, ๊ณ„์•ฝ๊ด€๋ฆฌ
customer_db 3 ๊ณ ๊ฐ ๊ฒ€์ƒ‰, ๊ณ„์•ฝ ์กฐํšŒ
rag_tools 2 ์•ฝ๊ด€/์š”์•ฝ์„œ RAG ๊ฒ€์ƒ‰

๊ธฐ์ˆ  ์Šคํƒ

์นดํ…Œ๊ณ ๋ฆฌ ๊ธฐ์ˆ  ์—ญํ• 
LLM ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜ LangGraph ReAct ๊ทธ๋ž˜ํ”„, ๋ฉ€ํ‹ฐํ„ด, ์กฐ๊ฑด๋ถ€ ๋ถ„๊ธฐ
LLM OpenRouter (qwen/qwen3-14b) ๋‹ค์ค‘ ๋ชจ๋ธ ๋ผ์šฐํŒ…
๋ฒกํ„ฐ DB ChromaDB ๋„๊ตฌ ๋ผ์šฐํŒ… + RAG ๊ฒ€์ƒ‰
์ž„๋ฒ ๋”ฉ multilingual-e5-large (1024d) ํ•œ๊ตญ์–ด ๋น„๋Œ€์นญ ๊ฒ€์ƒ‰
API ์„œ๋ฒ„ FastAPI REST + SSE ์ŠคํŠธ๋ฆฌ๋ฐ
MCP ์„œ๋ฒ„ FastMCP Claude Desktop/Cursor ์—ฐ๋™
PDF ํŒŒ์‹ฑ PyMuPDF ์•ฝ๊ด€/์š”์•ฝ์„œ ํ…์ŠคํŠธ ์ถ”์ถœ
๊ณ ๊ฐ DB SQLite3 ๊ณ ๊ฐ/๊ณ„์•ฝ ์‹œ๋ฎฌ๋ ˆ์ด์…˜

References

์ฃผ์ œ ์ถœ์ฒ˜
๋„๊ตฌ ์ˆ˜ ์ฆ๊ฐ€ ์‹œ ์ •ํ™•๋„ ์ €ํ•˜ How many tools can an AI Agent have?
RAG-MCP: ๋„๊ตฌ ๊ฒ€์ƒ‰ ํ›„ LLM์— ์ „๋‹ฌ WRITER Engineering
Tool Document Expansion (Tool-DE) arXiv 2510.22670
ํ•ฉ์„ฑ ์ฟผ๋ฆฌ ๊ธฐ๋ฐ˜ ๋„๊ตฌ ๊ฒ€์ƒ‰ (Re-Invoke) EMNLP 2024
๋Œ€๊ทœ๋ชจ ๋„๊ตฌ ๋ฒค์น˜๋งˆํฌ (ToolBench) ICLR 2024
๋ฒกํ„ฐ DB ๋น„๊ต (2025) Firecrawl ยท dev.to ยท TrueFoundry
๋ฒกํ„ฐ DB ๊ฐ€๊ฒฉ ๋น„๊ต Actian ยท Pinecone Pricing
Redis ๋ฒกํ„ฐ DB ๋น„๊ต Redis Blog
ํ•œ๊ตญ์–ด IR ๋ฒค์น˜๋งˆํฌ (Kor-IR) GitHub
multilingual-e5-large Hugging Face ยท arXiv 2402.05672
Multi-vector retrieval Pinecone
Query Rewriting / Advanced RAG Prompting Guide
LangGraph ๊ณต์‹ ๋ฌธ์„œ LangChain