- 语义去重:目前只做基于 chunk 键的去重,未做语义级去重
- 长期 Memory:目前只有进程内 / 会话内 memory,未做持久化长期记忆
- 多模态:目前以文本和 PDF 文本/表格抽取为主,未做图像/图表多模态理解
- 评估模块:目前缺少系统化的 retrieval / answer / tool-use 评估闭环
- 结构化 Chunk:目前仍是固定字符窗口切块,未做标题/段落/表格感知切块
- 知识图谱:目前缺少跨文档实体关系建模,难以稳定检索文档之间的关系
本项目是一个可运行的 本地 Agentic RAG(当前仅保留 CLI):
- 支持
.txt/.md/.pdf入库与向量化检索/关键词索引 - PDF 在文本提取之外,额外抽取表格并入库(可检索利润表/现金流量表等)
- 查询改写(Query Rewrite)+ 多查询召回(Multi-Query Retrieval)
- 混合检索(向量 + 关键词)+ 默认启用 reranker 重排
- 支持“遗漏补全”追问(如“你漏掉了一些公司”会触发重新检索)
- Agentic 工具链(
retrieve -> calculate / budget_analyst)与轨迹输出 - 内置反思循环:
reflect -> replan -> retry(默认最多重试 1 次) - 执行阶段耗时反馈(route / plan / reflect / replan / tool / answer / total)
- 多轮 memory 追问(复用上一轮变量与结果)
- Router Chain:先分类再决定是否进入检索链路
- 工具注册机制(可扩展
web_search/sql/file) - 预算分析师工具:根据年度预算做股价评级(
budget_analyst)
简化流程如下:
用户问题
-> Router 分类(闲聊 / 需要查询知识库 / 其他)
-> Planner 生成工具计划(默认 0~8 步,可配置)
-> Tool 执行(retrieve / calculate / budget_analyst)
-> Reflect 质量检查(是否需要重试)
-> Replan + Retry(最多 1 次,默认)
-> 汇总引用 + 轨迹
-> 最终回答
关键细节:
- Router Chain:优先判断问题类型,闲聊不进检索链路,避免性能浪费。
- Planner:根据问题/记忆决定是否需要检索或计算,默认最多 8 步(可配置)。
- Reflect / Replan / Retry:当检索无命中、计算变量缺失、工具运行异常等情况出现时,会自动反思并重规划。
- Tool 执行:
retrieve:混合检索(向量 + 关键词)+ 默认启用 rerank,写入memory。calculate:从检索文本中提取变量 + 安全表达式计算。budget_analyst:从年度预算与股价中生成增速、评分、评级。
- Memory:保存上轮变量、计算结果、引用,支持追问复用。
- Answer:根据轨迹与上下文生成最终答案(无上下文时不会乱编)。
python3 -m pip install -r requirements.txt必填:
LLM_API_URLLLM_API_KEYLLM_MODELEMBEDDING_API_URLEMBEDDING_API_KEYEMBEDDING_MODEL
建议配置(rerank 默认启用):
RERANKER_API_URLRERANKER_API_KEYRERANKER_MODEL
常用可选:
MILVUS_URI(默认./data/index/milvus.db)MILVUS_COLLECTION(默认rag_chunks)RAW_DATA_DIR(默认./knowledge)CHUNK_SIZE(默认1200)CHUNK_OVERLAP(默认180)RETRIEVAL_TOP_K(默认8)RETRIEVAL_CANDIDATE_K(默认64)HYBRID_VECTOR_WEIGHT(默认0.6)HYBRID_KEYWORD_WEIGHT(默认0.4)QUERY_REWRITE_ENABLED(默认true)MULTI_QUERY_ENABLED(默认true)MULTI_QUERY_COUNT(默认3)EMBEDDING_BATCH_SIZE(默认64)CHAT_HISTORY_MAX_MESSAGES(默认80)PLANNER_MAX_STEPS(默认8)PLANNER_RECENT_HISTORY_MESSAGES(默认20)ANSWER_MAX_CONTEXTS(默认16)ANSWER_MAX_TRACES(默认24)
把待检索文件放入 knowledge/,支持 .txt/.md/.pdf。
示例:
cp ~/docs/report.pdf knowledge/python3 scripts/ingest_once.py这一步会同时生成向量索引和 data/processed/chunks.jsonl,供关键词检索使用。
如只新增/更新单个文件,可增量 upsert:
python3 scripts/ingest_once.py --file knowledge/xxx.pdf方式一(推荐,自动走 conda 环境):
scripts/run_cli.sh --rebuild-index方式二(手动激活 conda 环境后运行):
source /home/nuku/miniconda3/bin/activate agentic-rag
python3 -m src.app.cli_chat --rebuild-index方式三(不激活环境,直接用 conda run):
/home/nuku/miniconda3/bin/conda run -n agentic-rag python -m src.app.cli_chat --rebuild-index输入问题即可。系统会根据 Router 分类决定是否检索。
示例:
你能做什么?
(不会触发检索)
请根据 688230_20260203_JJZK.pdf 的内容总结经营亮点
(会触发检索)
功能:将问题分为“闲聊 / 需要查询知识库 / 其他”,决定是否进入 RAG。
示例:
- 输入:
你好- 分类:闲聊 → 不检索
- 输入:
请根据文档说明营业收入变化原因- 分类:需要查询知识库 → 触发检索
实现方式(怎么实现的):
- 系统先把你的问题原样交给“路由提示词”,让模型只输出一个标签:闲聊 / 需要查询知识库 / 其他。
- 如果结果是“闲聊”,就直接走聊天回答,不会浪费时间检索文档。
- 如果结果是“需要查询知识库”,才会进入“规划器 + 工具链”流程。
- 如果结果是“其他”,会走简化的通用回答,不强制检索。
- 这一步只是分流,不做任何计算或检索;它的价值是节省成本、避免无关检索。
代码位置(可选):
src/agent/planner.py(路由逻辑)、src/llm/prompts.py(路由提示词)、src/agent/graph.py(分流后选择路径)
功能:先进行 Query Rewrite,再做 Multi-Query 召回(每条 query 走向量检索 + 关键词检索),最后合并候选并启用 rerank 重排。
示例问题:
请从 688230_20260203_JJZK.pdf 找到“净利润”相关描述
输出包含:
- 向量召回片段
- 关键词召回片段
- 引用来源与页码
- rerank 信息(默认启用,未配置会自动降级)
实现方式(怎么实现的):
- Query Rewrite:先将用户问题改写成更适合检索的一条查询,保留实体、时间、指标、变量名。
- Multi-Query:基于改写后的查询生成多个语义等价变体(默认 3 条),扩大召回覆盖面。
- 向量召回:每条 query 都转向量,在向量库里找最相近片段,并跨 query 聚合。
- 关键词召回:每条 query 都走 BM25,在本地 chunks 里找关键词匹配片段,并跨 query 聚合。
- Metadata 增强:chunk 持久化
doc_id/file_name/company_code/company_name/report_year/is_table等元数据。 - 覆盖优先:全局/补全类问题会按公司 metadata 做覆盖优先的结果选择,降低“只命中部分公司”概率。
- 关键词数据来源:chunks 来自
scripts/ingest_once.py生成的data/processed/chunks.jsonl。 - 合并候选:把两路结果按权重融合成一个候选池(权重默认 0.6 向量 / 0.4 关键词)。
- 默认启用 rerank:候选池交给重排模型做最终排序(配置好
RERANKER_*就会生效)。 - 写入 memory:最终结果写入 memory,后续追问可以直接复用。
代码位置(可选):
src/agent/tools/retrieve_tool.py、src/agent/tools/rag_retrieve.py
功能:对表达式进行安全计算,变量来自检索文本或 memory。
示例问题:
请根据文档计算 Q1_PROFIT + Q2_PROFIT - RD_COST
当变量已存在时:
把刚才结果再乘以 0.1
会使用 LAST_RESULT 直接计算。
实现方式(怎么实现的):
- 系统会先拿到你写的表达式(比如
A + B - C),然后把它“清洗”成标准格式。 - 变量从两个地方来:
- 检索到的文本(比如文档里出现的
A=100) - 上一次计算结果(自动放在
LAST_RESULT)
- 检索到的文本(比如文档里出现的
- 如果表达式里出现的变量都能找到,就进入安全计算器(只允许加减乘除和括号)。
- 计算得到的结果会存进 memory,下一轮可以直接继续“再乘以 0.1”这类追问。
代码位置(可选):
src/agent/tools/calculate_tool.py、src/agent/tools/calculator.py
功能:根据年度预算与股价信息生成“预算增速 + 评分 + 评级”。
示例问题:
请根据年度预算分析股价,给出分析评级
实现方式(怎么实现的):
- 先找数据:
- 如果你传的是 JSON(结构化输入),就直接读取年度预算和股价。
- 如果是自然语言,系统会从“问题 + 检索文本”里用规则抓取“预算金额”和“年份”。
- 再算增速:找到“最新年度预算”和“上一年预算”,计算同比增速(涨了多少百分比)。
- 再给评分:
- 增速高 -> 加分;增速低或下滑 -> 扣分
- 文本里如果出现“上调预算/下调预算”的语气,也会加/扣分
- 最后映射成评级:根据总分输出 买入/增持/中性/减持/卖出。
- 结果会写入 memory,后续可以继续问“用这个评分做计算”等。
代码位置(可选):
src/agent/tools/budget_analyst_tool.py
功能:自动保存变量和上轮计算结果,用于追问。
示例:
请计算 Q1_PROFIT + Q2_PROFIT把上一步结果减去 1000000
第二轮通常只触发 calculate,不会重复检索。
实现方式(怎么实现的):
- memory 就像一个小记事本,专门记住:上轮计算结果、提取的变量、检索到的片段。
- 每个工具执行完都会返回一份“增量更新”,系统把这些更新合并进记事本。
- 当你说“把上一步结果再乘以 0.1”,规划器会识别这是追问,就直接调用计算工具。
- 当你说“你漏掉了一些公司”这类补全追问,规划器会基于上一轮问题自动触发一次“全覆盖”检索。
代码位置(可选):
src/agent/memory.py、src/agent/planner.py
功能:执行工具链后自动做一轮反思;若判断当前结果质量不足,则重规划并重试一次(默认)。
常见触发场景:
retrieve返回no hitscalculate出现unknown variable- 工具运行时抛异常(会被记录为
tool_failed: ...,不直接中断主流程) - 路由为“需要查询知识库”但计划为空或无引用
实现方式(怎么实现的):
- 每轮工具执行后进入反思判定,输出
should_retry / reason / replan_feedback。 - 需要重试时,规划器会接收“上一次计划 + 上一次观察 + replan_feedback”重新生成步骤。
- 默认最多重试 1 次(
AgentExecutor(max_replan_retries=1))。
代码位置(可选):
src/agent/graph.py、src/agent/planner.py、src/llm/prompts.py
在对话中可使用:
/rebuild:重建索引/upsert <file>:增量更新单个文件到索引(不全量重建)/reset:清空会话 + memory/tools:查看已注册工具/memory:查看当前 memory 摘要/exit:退出
实现方式(怎么实现的):
- CLI 里以
/开头的输入会被当作命令处理,比如/tools、/memory。 /tools会列出当前注册的工具,让你确认系统能做哪些动作。/memory会打印当前记事本摘要,方便你知道系统“记住了什么”。- 若触发反思重试,CLI 的 Timing 会出现
reflect_*/replan_*阶段。
代码位置(可选):
src/app/cli_chat.py
scripts/ingest_once.py:构建索引(支持--file增量 upsert)scripts/query_once.py:单次 RAG 查询(含引用)scripts/agentic_query_once.py:单次 Agentic 演示(含轨迹)scripts/rebuild_index.py:仅重建索引scripts/run_cli.sh:推荐的 CLI 启动脚本
使用样例:
python3 scripts/query_once.py --question "这份文件主要讲什么?"- Agent 执行器:
src/agent/graph.py - Planner + Router:
src/agent/planner.py - Memory:
src/agent/memory.py - Tool Registry:
src/agent/tools/registry.py - Retrieve Tool:
src/agent/tools/retrieve_tool.py - Calculate Tool:
src/agent/tools/calculate_tool.py - Budget Analyst Tool:
src/agent/tools/budget_analyst_tool.py - CLI:
src/app/cli_chat.py - Prompt 模板:
src/llm/prompts.py
docs/multimodal_agentic_rag_plan.md
- 新增执行期反思循环:
reflect -> replan -> retry。 - 修复高风险问题:工具异常不再直接中断整次运行,改为观测并交给反思重试。
- 修复中风险问题:
finish作为控制信号处理,不再误报tool_not_registered。 - 修复中风险问题:Router 分类解析增加规范化和否定词规避(如“这不是闲聊”“不需要查询知识库”)。
- 修复中风险问题:知识库路由下空计划会触发补救重规划,避免直接无依据回答。