# rag_agent **Repository Path**: wangyuew/rag_agent ## Basic Information - **Project Name**: rag_agent - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-06-22 - **Last Updated**: 2026-08-07 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # LLM Growth Project 一个面向广告投放与广告合规场景的 RAG + Agent 应用工程项目。 项目目标不是做一个只会调用模型的 demo,而是完整练习 LLM 应用从检索、工具调用、结构化输出、后处理、debug 到 eval 的工程链路。 ## 30 秒看懂 这个项目可以理解为一个广告场景 Copilot 后端: - 用户问广告规则,例如“教育广告能不能写包过?”时,系统走 RAG 知识库,检索规则、生成答案并回填 evidence。 - 用户问投放效果,例如“少儿英语春季招生活动 CPA 为什么上涨?”时,系统走 Campaign Agent,读取指标、query、creative 和预算变更数据,再生成诊断报告。 - 用户问混合问题,例如“CPA 涨了,创意里能不能写包过?”时,系统通过 `/ask` 自动路由,同时调用 RAG 和 Campaign Agent,再合并成一个最终答案。 适合展示的工程能力: - FastAPI 后端接口设计 - OpenAI-compatible / Ollama / mock provider 抽象 - 场景化模型路由 - RAG 检索与 evidence 溯源 - 受控 Tool Agent 工具调用 - JSON 结构化输出、repair 和 fallback - 请求级 observability:LLM 调用次数、token、成本、耗时 - 离线 eval 与确定性测试 ## 推荐演示路径 如果只演示 5 分钟,建议按这个顺序: 1. `/ask` 广告规则问答:验证 RAG 和 evidence。 2. `/ask` 投放诊断:验证 Campaign Agent、工具调用和结构化诊断。 3. `/ask` 混合问题:验证统一路由、RAG + Agent 编排和答案合并。 4. `/ask/debug`:展示 route、campaign 解析、tool trace、raw answer、normalized answer。 详细演示话术见 [docs/demo_showcase.md](docs/demo_showcase.md)。 完整项目讲解见 [docs/project_walkthrough.md](docs/project_walkthrough.md)。 评测结果总览见 [docs/eval_scorecard.md](docs/eval_scorecard.md)。 展示物料清单见 [docs/showcase_assets.md](docs/showcase_assets.md)。 ## 最短路径 在仓库根目录执行: ```bash python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt bash scripts/start_demo.sh ``` `start_demo.sh` 默认使用 `mock + tfidf`,不需要 API Key 或 Ollama embedding;如果要接真实本地模型,可以执行: ```bash LLM_PROVIDER=ollama RAG_RETRIEVER_TYPE=hybrid bash scripts/start_demo.sh ``` 或者分别启动: ```bash source .venv/bin/activate LLM_PROVIDER=mock RAG_RETRIEVER_TYPE=tfidf python -m uvicorn gateway.app:app --reload --port 8000 python -m streamlit run frontend/streamlit_app.py ``` ## 核心能力 ```text RAG -> 广告规则知识库问答 -> TF-IDF / embedding / hybrid 检索 -> evidence 回填 -> retrieval / answer eval Campaign Agent -> 广告投放诊断 -> 单轮诊断 -> 多轮追问 -> memory -> deterministic followup -> debug / eval Tool Agent -> planner -> executor -> tool trace -> LLM shadow planner -> guardrail / fallback Unified Ask -> 自然语言统一入口 -> 自动路由 RAG / Agent / mixed -> campaign 名称解析 -> RAG + Agent 结果 merge -> /ask/chat 多轮入口 ``` ## 架构概览 ```text 用户问题 | v /ask or /ask/chat | v orchestrator_router.py | +-- RAG route | docs/policies/*.md | -> document_loader | -> vector store / embedding / hybrid | -> /rag/answer | +-- Campaign Agent route | campaign_resolver | -> tool_planner | -> tool_executor | -> analyzer | -> campaign diagnosis | +-- Mixed route RAG + Campaign Agent -> merge_unified_answers -> final_answer ``` ## 目录说明 ```text gateway/app.py FastAPI 应用创建和路由注册入口。 gateway/routes/ HTTP route 层,按 Core、RAG、Campaign Agent、Relevance、Unified Ask 等能力拆分 API。 gateway/common/ 配置、错误码、日志、JSON 解析、LLM client 等通用基础设施入口。 gateway/rag/ RAG 文档加载、检索、embedding、hybrid scorer、RAG answer service。 gateway/campaign/ Campaign Agent 的 tools、analyzer、planner、executor、memory、diagnosis service。 gateway/orchestrator/ /ask 统一入口路由、campaign 解析、RAG + Agent 跨能力编排 service。 evals/ RAG、Campaign Agent、Tool Agent、Unified Ask 的效果评测脚本。 evals/common/ 评测共享基建:metrics(Recall@k/MRR/分类指标)、retrieval、llm_judge。 tests/ 快速、确定性的工程测试脚本(含 tests/evals 指标单测)。 docs/ 阶段学习总结和设计文档。 data/ policy chunks、embedding、campaign mock data、eval reports。 ``` ## 快速开始 ```bash python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt ``` 安装 Ollama 模型: ```bash ollama pull qwen2.5:3b ollama pull nomic-embed-text ``` `.env` 示例: ```bash LLM_PROVIDER=ollama OPENAI_BASE_URL=http://127.0.0.1:11434/v1 OPENAI_API_KEY=ollama OPENAI_MODEL=qwen2.5:3b MODEL_RAG_QA=qwen2.5:3b MODEL_CAMPAIGN_DIAGNOSIS=qwen2.5:3b MODEL_QUERY_AD_RELEVANCE=qwen2.5:3b MODEL_TOOL_PLANNER=qwen2.5:3b MODEL_JSON_REPAIR=qwen2.5:3b EMBEDDING_BASE_URL=http://127.0.0.1:11434/api/embed EMBEDDING_MODEL=nomic-embed-text EMBEDDING_CACHE_ENABLED=true HYBRID_ALPHA=0.5 HYBRID_BETA=0.5 ``` `LLM_PROVIDER` 支持: ```text ollama openai_compatible mock ``` 其中 `ollama` 和 `openai_compatible` 都走 OpenAI-compatible Chat Completions 协议,只是 base_url/model 配置不同;`mock` 用于本地工程测试和无模型环境的链路验证。 模型选择分两层: ```text LLM_PROVIDER -> 决定调用哪个模型服务,例如 ollama/openai_compatible/mock MODEL_* -> 决定不同业务场景使用哪个模型 ``` 模型路由优先级: ```text 接口显式传入 model > MODEL_RAG_QA / MODEL_CAMPAIGN_DIAGNOSIS / MODEL_JSON_REPAIR 等业务配置 > scene_config.default_model > OPENAI_MODEL ``` 构建 RAG 数据: ```bash python -m gateway.rag.document_loader python -m gateway.rag.build_embeddings ``` 启动服务: ```bash uvicorn gateway.app:app --reload --port 8000 ``` 启动最小前端: ```bash streamlit run frontend/streamlit_app.py ``` 前端里有五个 Tab:`Unified Ask`、`Chat`、`RAG`、`Campaign Agent`、`Debug`。 ## 常用 API ### RAG 问答 ```bash curl -X POST http://127.0.0.1:8000/rag/answer \ -H "Content-Type: application/json" \ -d '{ "question": "教育广告能不能写包过?", "top_k": 3, "retriever_type": "hybrid" }' ``` ### Campaign 单轮诊断 ```bash curl -X POST http://127.0.0.1:8000/campaign/diagnose \ -H "Content-Type: application/json" \ -d '{ "campaign_id": "campaign_001", "question": "最近 7 天 CPA 为什么上涨?" }' ``` ### Tool Agent 诊断 ```bash curl -X POST http://127.0.0.1:8000/campaign/tool-agent/diagnose \ -H "Content-Type: application/json" \ -d '{ "campaign_id": "campaign_001", "question": "哪些 query 可能拉高了 CPA?" }' ``` ### 统一自然语言入口 ```bash curl -X POST http://127.0.0.1:8000/ask \ -H "Content-Type: application/json" \ -d '{ "message": "少儿英语春季招生最近 CPA 涨了,创意里能不能写包过?" }' ``` ### 统一入口多轮追问 ```bash curl -X POST http://127.0.0.1:8000/ask/chat \ -H "Content-Type: application/json" \ -d '{ "session_id": "demo_session_001", "message": "少儿英语那个计划 CPA 怎么涨了?" }' curl -X POST http://127.0.0.1:8000/ask/chat \ -H "Content-Type: application/json" \ -d '{ "session_id": "demo_session_001", "message": "那先处理哪个 query?" }' ``` ## Debug API ```text /campaign/diagnose/debug /campaign/chat/debug /campaign/tool-agent/debug /ask/debug ``` Debug 接口用于观察: - router 结果 - campaign 识别结果 - tool plan - tool trace - raw LLM answer - normalized answer - merge result ## 一键演示 ```bash python -m gateway.demo ``` 演示内容: - RAG 广告规则问答 - Campaign Agent 单轮诊断 - Tool Agent trace - Unified Ask mixed 调用 - Unified Ask Chat 多轮追问 ## 回归评测 RAG: ```bash # 检索层:Recall@k / MRR / Precision@k(确定性) python -m evals.rag.evaluate_retrieval python -m evals.rag.evaluate_embedding_retrieval python -m evals.rag.evaluate_hybrid_retrieval # 答案层:分类指标 + forbidden 安全护栏 + LLM-as-judge # 接了真模型才有真实 judge 分;mock 下为确定性桩分,仅验证流水线 python -m evals.rag.evaluate_answer tfidf python -m evals.rag.evaluate_answer embedding python -m evals.rag.evaluate_answer hybrid # 汇总成对比表 docs/eval_scorecard.md python -m evals.rag.summarize_eval_reports ``` 评测分层说明见下方「设计亮点 1.5」和 `docs/day_eval_real_evaluation_upgrade.md`。 Campaign Agent: ```bash python -m evals.campaign.evaluate_diagnosis python -m evals.campaign.evaluate_chat ``` Tool Agent: ```bash python -m evals.campaign.evaluate_tool_agent python -m evals.campaign.evaluate_tool_trace python -m evals.campaign.evaluate_llm_tool_planner ``` Unified Ask: ```bash python -m evals.orchestrator.evaluate_campaign_resolver python -m evals.orchestrator.evaluate_unified_ask python -m evals.orchestrator.evaluate_unified_ask_debug python -m evals.orchestrator.evaluate_unified_ask_chat ``` 工程测试: ```bash python -m tests.rag.test_engineering_guards python -m tests.campaign.test_followup_intent python -m tests.evals.test_metrics python -m tests.common.test_observability ``` ## 持续集成 (CI) 仓库包含 [.github/workflows/ci.yml](.github/workflows/ci.yml),用于 GitHub 托管或 GitHub 镜像仓库的 push / PR 检查,全程 `LLM_PROVIDER=mock`(零网络、确定性)。当前 git remote 是 Gitee,Gitee 不会自动执行 GitHub Actions;本地可以用下面的命令运行同一组核心门禁: ```bash LLM_PROVIDER=mock python -m tests.api.test_smoke LLM_PROVIDER=mock python -m tests.rag.test_engineering_guards LLM_PROVIDER=mock python -m tests.evals.test_retrieval_regression ``` ```text 单测门禁 metrics / observability / engineering guards / model router / followup 检索回归门禁 tfidf recall@3 / mrr 设硬阈值,掉下去直接红 eval 流水线冒烟 mock 下跑通 answer / unified_ask / retrieval / scorecard,验链路不崩 产物 上传 docs/eval_scorecard.md 作为 artifact ``` CI 边界(刻意划清): ```text 守护得了:代码不崩、指标算法不回归、检索质量不掉、provider 契约不破 守护不了:答案层真实 LLM-judge 分数(需 Ollama,CI 无模型)-> 放本地/定时任务 ``` `mock` provider 是 CI 的地基:正因为有它,整条链路才能在没有模型的环境里确定性跑通。 ## 设计亮点 ### 1. RAG 不是只召回文本 - 支持多 retriever:`tfidf`、`embedding`、`hybrid` - hybrid scorer 融合 TF-IDF、embedding、业务 boost - answer 必须返回 evidence chunk id - 后处理会校验 evidence 是否真实存在 ### 1.5 Eval 不是只数关键词 评测按"回答质量的三个独立问题"分层,不再用单一关键词命中糊在一起: ```text 检索层 -> Recall@k / MRR / Precision@k (确定性,evals/common/metrics.py) 结构层 -> risk / material 分类准确率 + 混淆矩阵 (确定性) 生成层 -> LLM-as-judge 四维打分 (faithfulness/relevance/completeness/safety) 安全层 -> forbidden 硬护栏(否定语境免疫) (确定性,背书违规表达直接判危险) ``` - 关键词命中降级为 smoke 信号,只用来发现"完全跑题" - golden set 含 `happy_path` / `adversarial` / `out_of_scope` 分片,专门放 bad case - judge 在 `mock` provider 下返回确定性桩分,保证整条流水线可进 CI - `python -m evals.rag.summarize_eval_reports` 生成 `docs/eval_scorecard.md` 对比表 生成 scorecard: ```bash python -m evals.rag.evaluate_retrieval python -m evals.rag.evaluate_embedding_retrieval python -m evals.rag.evaluate_hybrid_retrieval python -m evals.rag.evaluate_answer tfidf python -m evals.rag.evaluate_answer embedding python -m evals.rag.evaluate_answer hybrid python -m evals.rag.summarize_eval_reports python -m tests.evals.test_metrics ``` ### 2. Agent 不只靠 Prompt Campaign Agent 中,LLM 负责组织语言,但关键边界由服务端兜底: - `pre_analysis` 生成确定性业务 insight - root causes / evidences / suggestions 会被 normalize - 健康 campaign 会被服务端纠偏 - raw answer 可以错,final answer 必须稳 ### 3. Tool Agent 有 Trace Tool Agent 不是一次性取全量数据,而是: ```text planner -> executor -> analyzer -> answer ``` Debug 中可以看到: - 计划调用哪些工具 - 实际执行哪些工具 - 每个工具输入、输出摘要、耗时和状态 ### 4. LLM Planner 只做 Shadow 项目尝试了 LLM planner,但没有直接上线替换规则 planner。 原因是初始评测中 LLM planner 会出现: - focus 非法 - 多选工具 - 倾向全量取数 因此增加了: - focus whitelist - tool whitelist - tools_for_focus - rule fallback - shadow eval ### 5. RAG + Agent 统一编排 `/ask` 可以处理: - 纯规则问题 -> RAG - 纯投放问题 -> Agent - 混合问题 -> RAG + Agent + merge 这更接近真实 AI 应用的入口形态。 ### 6. 请求级可观测性铺全链路 用 `contextvars` 给每个 HTTP 请求开一条 trace,请求内所有 LLM 调用自动记入, 业务代码零改动: ```text FastAPI middleware -> start_trace() 每个请求开一条 trace -> LLMClient 记录每次调用 latency / prompt·completion tokens / cost -> trace.summary() 聚合成请求级 token/成本/耗时(按 scene 拆分) ``` - token 优先用 provider 上报的真实 usage,缺失时启发式估算并打标 `tokens_estimated` - 成本按每千 token 单价估算,本地 ollama 记 0 - 每个响应带上 `X-LLM-Calls / X-LLM-Total-Tokens / X-LLM-Cost-Usd / X-Request-Latency-Ms` 头 - 每个请求打一条结构化汇总日志;`/rag/answer` 响应体还内嵌完整调用瀑布 `observability` 一个 `/ask` 混合请求会自动聚合 RAG + Agent 的多次 LLM 调用,一眼看到总 token 和成本。 详见 `docs/day_request_observability.md`。 ## 当前限制 - campaign 数据仍是 mock JSON - memory 仍是内存版,服务重启会丢 - router / resolver 主要是规则版 - mixed query decomposition 仍比较简单 - RAG 答案层的 LLM-judge 真实分数依赖本地起 Ollama;mock 下只跑通流水线 - campaign / unified ask 的 eval 尚未迁到分层评测(仍是关键词命中) - 成本估算单价表是量级参考,未接真实计费;本地 ollama 记 0 成本 - CI workflow 已加入单测、API smoke、检索回归和 mock eval 冒烟;当前 Gitee remote 不会自动触发 GitHub Actions - 没有权限控制 - Streamlit 前端是最小演示界面,还没有生产级前端、鉴权和部署配置 - 没有 Docker 部署 ## 推荐阅读 - `docs/rag_learning_summary.md` - `docs/day_campaign_agent_stage_summary.md` - `docs/day_campaign_tool_agent.md` - `docs/day_unified_ask_orchestrator.md` - `docs/day_campaign_chat_memory.md` - `docs/day_campaign_002_agent_guardrails.md` - `docs/day_eval_real_evaluation_upgrade.md` - `docs/eval_scorecard.md` - `docs/day_request_observability.md`