From e24d9804bada2d30993c37adaca14b74d542db0a Mon Sep 17 00:00:00 2001 From: bruce Date: Fri, 29 May 2026 23:02:54 +0800 Subject: [PATCH] =?UTF-8?q?docs(design):=20=E8=A1=A5=E5=85=A8=E4=B8=AD?= =?UTF-8?q?=E6=96=87=E8=AE=BE=E8=AE=A1=E6=96=87=E6=A1=A3=E4=BD=93=E7=B3=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/设计文档/0.设计文档索引.md | 71 +++++ .../1.智能体总体设计.md} | 16 +- docs/设计文档/2.功能流程设计.md | 169 ++++++++++++ docs/设计文档/3.数据库设计.md | 144 ++++++++++ docs/设计文档/4.页面与路由设计.md | 179 ++++++++++++ docs/设计文档/5.部署设计.md | 103 +++++++ docs/设计文档/模块设计/1.配置模块详细设计.md | 106 +++++++ docs/设计文档/模块设计/2.场景模块详细设计.md | 134 +++++++++ docs/设计文档/模块设计/3.文档模块详细设计.md | 127 +++++++++ docs/设计文档/模块设计/4.对话模块详细设计.md | 118 ++++++++ docs/设计文档/模块设计/5.审计模块详细设计.md | 121 ++++++++ .../模块设计/6.智能核心模块详细设计.md | 259 ++++++++++++++++++ 12 files changed, 1539 insertions(+), 8 deletions(-) create mode 100644 docs/设计文档/0.设计文档索引.md rename docs/{agent_design.md => 设计文档/1.智能体总体设计.md} (88%) create mode 100644 docs/设计文档/2.功能流程设计.md create mode 100644 docs/设计文档/3.数据库设计.md create mode 100644 docs/设计文档/4.页面与路由设计.md create mode 100644 docs/设计文档/5.部署设计.md create mode 100644 docs/设计文档/模块设计/1.配置模块详细设计.md create mode 100644 docs/设计文档/模块设计/2.场景模块详细设计.md create mode 100644 docs/设计文档/模块设计/3.文档模块详细设计.md create mode 100644 docs/设计文档/模块设计/4.对话模块详细设计.md create mode 100644 docs/设计文档/模块设计/5.审计模块详细设计.md create mode 100644 docs/设计文档/模块设计/6.智能核心模块详细设计.md diff --git a/docs/设计文档/0.设计文档索引.md b/docs/设计文档/0.设计文档索引.md new file mode 100644 index 0000000..6629cf1 --- /dev/null +++ b/docs/设计文档/0.设计文档索引.md @@ -0,0 +1,71 @@ +# 模块详细设计文档索引 + +## 1. 设计文档说明 + +本目录存放 Universal Agent Demo Framework V1 的设计文档。需求文档回答“要做什么”,设计文档回答“怎么实现、边界在哪里、如何验证”。 + +文档命名统一使用中文编号,便于复试讲解和按顺序阅读。 + +## 2. 模块设计文档列表 + +| 顺序 | 文档 | 说明 | +|---|---|---| +| 0 | `0.设计文档索引.md` | 当前索引 | +| 1 | `1.智能体总体设计.md` | 智能核心总体链路、配置、输出和 Adapter | +| 2 | `2.功能流程设计.md` | 复试准备、演示、上传、入库、对话和审计流程 | +| 3 | `3.数据库设计.md` | Django 数据模型、字段、索引和初始化策略 | +| 4 | `4.页面与路由设计.md` | 页面结构、URL、跳转和异常状态 | +| 5 | `5.部署设计.md` | 本地、Docker、环境变量和持久化 | + +模块详细设计位于 `模块设计/`: + +| 模块 | 文档 | +|---|---| +| 配置 | `模块设计/1.配置模块详细设计.md` | +| 场景 | `模块设计/2.场景模块详细设计.md` | +| 文档 | `模块设计/3.文档模块详细设计.md` | +| 对话 | `模块设计/4.对话模块详细设计.md` | +| 审计 | `模块设计/5.审计模块详细设计.md` | +| 智能核心 | `模块设计/6.智能核心模块详细设计.md` | + +## 3. 模块依赖关系 + +```text +config + |-- apps.scenarios + |-- apps.documents + |-- apps.chat + |-- apps.audit + +apps.scenarios + |-- reads configs/*.yaml + +apps.documents + |-- depends on apps.scenarios + |-- calls agent_core.rag.ingest + +apps.chat + |-- depends on apps.scenarios + |-- calls agent_core.orchestrator + |-- calls apps.audit.services + +apps.audit + |-- stores AgentResult snapshots + +agent_core + |-- consumes scenario config + |-- uses RAG, tools, LLM provider and structured output parser +``` + +## 4. 推荐阅读顺序 + +1. `docs/需求分析/1.V1总需求文档.md` +2. `docs/需求分析/2.模块需求索引.md` +3. `docs/设计文档/1.智能体总体设计.md` +4. `docs/设计文档/2.功能流程设计.md` +5. `docs/设计文档/3.数据库设计.md` +6. `docs/设计文档/4.页面与路由设计.md` +7. `docs/设计文档/5.部署设计.md` +8. `docs/设计文档/模块设计/*.md` + +后续编码时,每个模块应先对照对应需求文档和详细设计,再实现模型、服务、视图和测试。 diff --git a/docs/agent_design.md b/docs/设计文档/1.智能体总体设计.md similarity index 88% rename from docs/agent_design.md rename to docs/设计文档/1.智能体总体设计.md index 44d51c9..bb9ef1f 100644 --- a/docs/agent_design.md +++ b/docs/设计文档/1.智能体总体设计.md @@ -1,4 +1,4 @@ -# Agent 设计文档 +# 智能体总体设计文档 ## 1. 设计目标 @@ -50,7 +50,7 @@ V1 预置 5 类 Agent 场景: ## 4. 场景配置结构 -场景配置建议使用 YAML。 +场景配置使用 YAML,V1 以配置文件作为场景唯一事实来源,后台管理不作为场景配置入口。 ```yaml id: quality_analysis @@ -60,6 +60,7 @@ description: 用于分析生产质量异常、检索 SOP、生成处理建议 agent: role: 质量管理专家 goal: 根据用户问题、知识库和工具结果,输出可执行的质量分析报告 + system_prompt: "" instructions: - 回答必须基于知识库或工具结果 - 不确定时必须说明缺失信息 @@ -71,8 +72,8 @@ rag: top_k: 5 tools: - - get_recent_defect_records - - calculate_defect_rate + - query_demo_records + - calculate_rate output: type: quality_report @@ -122,7 +123,7 @@ RAG 在 V1 中负责给 Agent 提供题目材料和业务知识。 ```text 用户问题 ↓ -按 scenario_id 过滤 +按 scenario_id 和可选 document_ids 过滤 ↓ 向量检索 top_k ↓ @@ -193,7 +194,7 @@ Agent Core 统一返回: ## 10. Adapter 策略 -V1 默认使用自研轻量 Orchestrator。 +V1 默认使用自研轻量 Orchestrator,通过 OpenAI 兼容接口接入 LLM 与 Embedding,可自主选择 OpenAI、硅基流动等兼容服务。 后续可以扩展: @@ -204,8 +205,7 @@ V1 默认使用自研轻量 Orchestrator。 所有 Adapter 应保持统一接口: ```text -run(scenario_config, user_input, options=None) -> AgentResult +run_agent(scenario_config, user_input, options=None) -> AgentResult ``` 这样可以保证 Django 业务层不受底层 Agent 编排实现影响。 - diff --git a/docs/设计文档/2.功能流程设计.md b/docs/设计文档/2.功能流程设计.md new file mode 100644 index 0000000..88b2fc7 --- /dev/null +++ b/docs/设计文档/2.功能流程设计.md @@ -0,0 +1,169 @@ +# V1 功能设计文档 + +## 1. 功能设计目标 + +V1 的功能设计目标是让复试展示者在本地快速完成一个可讲解、可演示、可改题的 Agent Demo。系统不追求复杂平台能力,而是优先保证以下闭环稳定: + +- 场景配置可选择。 +- 文档可上传并入库。 +- 用户可在场景下发起对话。 +- Agent 可返回结构化结果、引用来源和工具调用记录。 +- 每次成功或失败的对话都有审计记录。 +- 本地和 Docker 均可启动。 + +## 2. 用户角色 + +V1 仅设计一个用户角色:Demo 操作者。 + +该角色负责启动系统、选择场景、上传材料、触发入库、发起对话、查看输出和审计日志。系统不在 V1 中区分管理员、审核员、普通用户等权限角色。 + +## 3. 核心业务流程 + +```text +启动系统 + ↓ +查看 5 个预置场景 + ↓ +选择场景 + ↓ +上传题目材料 + ↓ +触发知识库入库 + ↓ +发起 Agent 对话 + ↓ +查看结构化输出、引用和工具调用 + ↓ +查看审计日志 +``` + +任一环节失败时,页面应给出明确提示,并尽量保留用户已完成的上下文。 + +## 4. 场景选择流程 + +1. 首页调用 `apps.scenarios.services.list_scenarios()`。 +2. 服务从 `configs/` 读取 YAML 场景配置。 +3. 校验必填字段、工具名称和输出类型。 +4. 页面展示场景名称、描述、适用题型、启用状态。 +5. 用户点击进入 `/chat//`。 + +异常处理: + +- 配置目录不存在:展示空状态和配置目录提示。 +- 单个配置非法:不阻断其他配置,页面展示该配置错误。 +- 场景不存在:跳转或渲染错误页,提示检查场景 ID。 + +## 5. 文件上传流程 + +1. 用户进入 `/documents/upload/`。 +2. 页面加载可用场景下拉框。 +3. 用户选择场景并上传 `.txt`、`.md`、`.pdf` 或 `.docx` 文件。 +4. Documents 模块校验文件类型和大小。 +5. 保存文件到 `UPLOAD_ROOT//`。 +6. 写入 `UploadedDocument` 记录,状态为 `uploaded`。 +7. 返回文件列表页并展示上传结果。 + +V1 文件上传默认手动入库,避免上传大文件时页面阻塞过久。 + +## 6. 文档入库流程 + +1. 用户在文件列表点击“入库”。 +2. Documents 模块读取文件并抽取文本。 +3. 调用 `agent_core.rag.ingest.ingest_document()`。 +4. Agent Core 按固定长度切分文本。 +5. 写入本地 Chroma collection。 +6. 入库成功:更新状态为 `indexed`。 +7. 入库失败:更新状态为 `failed`,保存错误信息。 + +文本为空、文件丢失、向量库不可写都应进入失败状态,不能让页面报 500。 + +## 7. Agent 对话流程 + +```text +用户提交问题 + ↓ +Chat 表单校验 + ↓ +Scenarios 加载场景配置 + ↓ +Agent Core 执行 run_agent() + ↓ +RAG 按场景和可选文档范围检索知识片段 + ↓ +工具系统执行可用工具 + ↓ +LLM Provider 生成结果 + ↓ +结构化输出解析 + ↓ +Audit 写入日志 + ↓ +Chat 页面展示结果 +``` + +Chat 模块只负责请求处理和页面展示,不直接写 RAG、工具和模型调用细节。 + +## 8. RAG 检索流程 + +1. Orchestrator 读取场景配置中的 `rag.enabled`、`collection`、`top_k`。 +2. 若启用 RAG,则调用 `agent_core.rag.retriever.retrieve()`。 +3. 检索必须按 `scenario_id` 过滤,避免跨场景污染。 +4. 如果用户在对话页选择了文档,则同时按 `document_ids` 过滤;未选择时使用当前场景全部已入库文档。 +5. 返回片段内容、来源文件、chunk ID、分数。 +6. 片段进入 Prompt,同时随 AgentResult 返回给页面和审计日志。 + +检索失败时,AgentResult 应记录错误或警告;若业务允许,可继续使用非 RAG 上下文回答。 + +## 9. 工具调用流程 + +1. 场景配置声明可用工具名称。 +2. Orchestrator 从 Tool Registry 查询工具。 +3. 对不可用工具记录失败,不中断整个流程。 +4. 内置工具按统一参数和返回结构执行。 +5. 工具结果进入 Prompt 或结构化输出上下文。 +6. 所有工具调用写入 AgentResult 和审计日志。 + +V1 先采用“配置声明 + Orchestrator 决策”的轻量策略,不实现复杂多轮工具调用协议。 + +## 10. 审计日志流程 + +1. Chat 模块在 Agent Core 返回后调用 `apps.audit.services.create_audit_log()`。 +2. 成功结果记录输入、输出、引用、工具调用、模型名和耗时。 +3. 失败结果也记录场景、输入、错误信息和已产生的中间结果。 +4. 日志中不得保存 `LLM_API_KEY`、环境变量完整内容或上传文件绝对敏感路径。 +5. 审计列表展示摘要,详情页展示完整 JSON 片段。 + +## 11. 复试改题流程 + +1. 判断题目最接近的模板。 +2. 复制 `configs/` 中相近 YAML。 +3. 修改场景名称、角色、目标、指令和输出类型。 +4. 上传题目文档并入库。 +5. 如题目需要计算或查询,新增一个内置工具并在场景中声明。 +6. 用 2 到 3 个问题验证输出和审计链路。 +7. 演示时重点展示配置、知识库、工具调用、结构化结果和审计日志。 + +## 12. 异常处理流程 + +| 异常 | 处理方式 | +|---|---| +| 场景配置缺失 | 页面展示错误,保留返回首页入口 | +| 场景字段非法 | 标记非法配置,不影响其他场景 | +| 上传文件类型不支持 | 表单错误提示 | +| 文件读取失败 | 文档状态改为 `failed` | +| RAG 入库失败 | 记录错误信息并允许重试 | +| LLM 配置缺失 | AgentResult 返回失败,审计日志记录失败 | +| 工具调用失败 | 记录工具失败,流程尽量继续 | +| 结构化解析失败 | 展示原始输出并记录解析错误 | + +## 13. V1 功能验收标准 + +- 首页可以展示 5 个预置场景。 +- 场景配置来自 YAML 文件。 +- 可以上传 `.txt`、`.md`、`.pdf` 和 `.docx` 文件。 +- 文件可触发入库,并显示 `uploaded`、`indexed`、`failed` 状态。 +- 可以进入任一场景对话页并提交问题。 +- AgentResult 至少包含回答、结构化输出、引用、工具调用、耗时和状态。 +- 成功和失败对话都能生成审计日志。 +- 审计详情可以解释一次 Agent 输出的输入、依据和过程。 +- 本地启动和 Docker 启动路径清晰可执行。 diff --git a/docs/设计文档/3.数据库设计.md b/docs/设计文档/3.数据库设计.md new file mode 100644 index 0000000..cc061ac --- /dev/null +++ b/docs/设计文档/3.数据库设计.md @@ -0,0 +1,144 @@ +# V1 数据库设计文档 + +## 1. 数据库设计目标 + +V1 数据库设计优先服务本地演示、讲解清晰和快速改题。数据模型只覆盖文件、对话、审计和简单示例业务数据,不引入复杂权限、多租户或工作流状态机。 + +## 2. 数据库选型 + +默认使用 SQLite,数据库文件位于 `data/db.sqlite3`。SQLite 适合复试现场单机运行,便于 Docker 挂载和备份。 + +后续如需多人协作或更正式部署,可通过 Django settings 切换到 PostgreSQL,但 V1 不强制实现。 + +## 3. 表结构总览 + +| 表 | Django Model | 模块 | 说明 | +|---|---|---|---| +| uploaded_document | `UploadedDocument` | Documents | 上传文件元数据和入库状态 | +| agent_audit_log | `AgentAuditLog` | Audit | Agent 执行审计快照 | +| demo_business_record | `DemoBusinessRecord` | Agent Core / Tools | 内置工具可查询的模拟业务数据 | +| chat_session | `ChatSession` | Chat | 可选,对话会话 | +| chat_message | `ChatMessage` | Chat | 可选,对话消息 | + +## 4. UploadedDocument 表设计 + +| 字段 | 类型 | 约束 | 说明 | +|---|---|---|---| +| id | BigAutoField | PK | 主键 | +| scenario_id | CharField(100) | indexed | 关联场景 ID | +| original_name | CharField(255) | required | 原始文件名 | +| file | FileField | required | 文件相对路径 | +| file_type | CharField(20) | required | `txt`、`md`、`pdf`、`docx` 等 | +| size | PositiveIntegerField | default 0 | 字节数 | +| status | CharField(20) | indexed | `uploaded`、`indexed`、`failed` | +| error_message | TextField | blank | 入库失败原因 | +| created_at | DateTimeField | auto_now_add | 上传时间 | +| updated_at | DateTimeField | auto_now | 更新时间 | + +状态流转: + +```text +uploaded -> indexed +uploaded -> failed +failed -> indexed +failed -> failed +``` + +重新入库时应按文档维度覆盖或清理旧 chunk,避免同一文件重复出现在向量检索结果中。文档选择范围由 Chat 表单本次提交的 `document_ids` 传入 Agent Core,V1 不需要为该选择单独建表。 + +## 5. AgentAuditLog 表设计 + +| 字段 | 类型 | 约束 | 说明 | +|---|---|---|---| +| id | BigAutoField | PK | 主键 | +| scenario_id | CharField(100) | indexed | 场景 ID | +| scenario_name | CharField(200) | blank | 场景名称快照 | +| user_input | TextField | required | 用户输入 | +| retrieved_chunks | JSONField | default list | RAG 引用片段 | +| tool_calls | JSONField | default list | 工具调用记录 | +| structured_output | JSONField | default dict | 结构化输出 | +| final_answer | TextField | blank | 最终回答 | +| raw_output | TextField | blank | 模型原始输出 | +| model_name | CharField(100) | blank | 模型名称 | +| latency_ms | PositiveIntegerField | default 0 | 执行耗时 | +| status | CharField(20) | indexed | `success`、`failed` | +| error_message | TextField | blank | 错误信息 | +| created_at | DateTimeField | auto_now_add, indexed | 创建时间 | + +审计日志保存的是执行快照,不依赖场景配置后续是否被修改。 + +## 6. DemoBusinessRecord 表设计 + +| 字段 | 类型 | 约束 | 说明 | +|---|---|---|---| +| id | BigAutoField | PK | 主键 | +| scenario_id | CharField(100) | indexed | 适用场景 | +| record_type | CharField(100) | indexed | 记录类型,如 defect、ticket、invoice | +| title | CharField(255) | required | 标题 | +| payload | JSONField | default dict | 模拟业务数据 | +| created_at | DateTimeField | auto_now_add | 创建时间 | + +该表为 V1 必需表,用于 `query_demo_records` 工具,避免工具只能返回硬编码数据。Django Admin 可以管理该表的数据,场景 YAML 仍不在 Admin 中编辑。 + +## 7. ChatSession 表设计 + +V1 可先不实现会话持久化。如果实现,字段建议如下: + +| 字段 | 类型 | 说明 | +|---|---|---| +| id | BigAutoField | 主键 | +| scenario_id | CharField(100) | 场景 ID | +| title | CharField(255) | 会话标题 | +| created_at | DateTimeField | 创建时间 | +| updated_at | DateTimeField | 更新时间 | + +## 8. ChatMessage 表设计 + +V1 可通过审计日志满足演示追踪,不强制实现消息表。如果实现,字段建议如下: + +| 字段 | 类型 | 说明 | +|---|---|---| +| id | BigAutoField | 主键 | +| session | ForeignKey(ChatSession) | 所属会话 | +| role | CharField(20) | `user`、`assistant`、`system` | +| content | TextField | 消息内容 | +| audit_log | ForeignKey(AgentAuditLog, null=True) | 关联审计 | +| created_at | DateTimeField | 创建时间 | + +## 9. 表关系设计 + +```text +Scenario YAML + |-- scenario_id + |-- UploadedDocument.scenario_id + |-- AgentAuditLog.scenario_id + |-- DemoBusinessRecord.scenario_id + |-- ChatSession.scenario_id + +ChatSession 1 -- N ChatMessage +ChatMessage 0/1 -- 1 AgentAuditLog +``` + +场景配置 V1 存在 YAML 中,不建 `Scenario` 数据表。这样更方便复试现场复制和修改配置文件。 + +## 10. 索引设计 + +- `UploadedDocument(scenario_id, status)`:用于按场景查看文件和入库状态。 +- `AgentAuditLog(scenario_id, created_at)`:用于按场景查看最近日志。 +- `AgentAuditLog(status, created_at)`:用于排查失败日志。 +- `DemoBusinessRecord(scenario_id, record_type)`:用于工具查询模拟数据。 + +## 11. 数据初始化策略 + +- 场景初始化:读取 `configs/*.yaml`,不写数据库。 +- 示例业务数据:可提供 Django management command 初始化 `DemoBusinessRecord`。 +- 超级用户:本地演示可手动创建,Docker 可通过说明引导创建。 +- 上传文件和 Chroma 数据:存放在 `data/` 下,通过 Docker volume 持久化。 + +## 12. 后续扩展方向 + +- 增加 `Scenario` 表,实现后台编辑场景。 +- 增加 `ToolCallLog` 独立表,用于复杂工具审计。 +- 使用 PostgreSQL JSONB 优化 JSON 查询。 +- 增加用户和权限模型。 +- 增加文档 chunk 元数据表,便于从数据库追踪向量库内容。 diff --git a/docs/设计文档/4.页面与路由设计.md b/docs/设计文档/4.页面与路由设计.md new file mode 100644 index 0000000..d8f5bdb --- /dev/null +++ b/docs/设计文档/4.页面与路由设计.md @@ -0,0 +1,179 @@ +# V1 页面与路由设计文档 + +## 1. 页面设计目标 + +V1 页面使用 Django Templates,优先保证清晰、稳定、可讲解。页面应围绕复试演示的主路径组织:选择场景、上传文档、入库、对话、查看审计。 + +## 2. 页面列表 + +| 页面 | 路径 | 模块 | 说明 | +|---|---|---|---| +| 首页/场景列表 | `/` | Scenarios | 展示 5 个预置场景 | +| Agent 对话页 | `/chat//` | Chat | 提交问题并展示结果 | +| 文件列表页 | `/documents/` | Documents | 查看上传文件和入库状态 | +| 文件上传页 | `/documents/upload/` | Documents | 上传题目材料 | +| 文档入库动作 | `/documents//index/` | Documents | POST 触发入库 | +| 审计日志列表 | `/audit/` | Audit | 查看对话记录 | +| 审计日志详情 | `/audit//` | Audit | 查看单次执行详情 | +| Django Admin | `/admin/` | Config | 后台管理 | + +## 3. 路由总览 + +```text +config.urls + |-- "" -> apps.scenarios.urls + |-- "chat/" -> apps.chat.urls + |-- "documents/" -> apps.documents.urls + |-- "audit/" -> apps.audit.urls + |-- "admin/" -> django.contrib.admin +``` + +各模块只暴露自己的 URL,避免把业务路由集中写在 `config.urls` 中。 + +## 4. 首页与场景列表页 + +路径:`/` + +展示内容: + +- 系统名称和简短定位。 +- 5 个场景卡片或列表。 +- 场景名称、描述、适用题型、启用状态。 +- “进入对话”按钮。 +- 文件管理和审计日志入口。 + +错误状态: + +- 没有可用场景:展示配置目录提示。 +- 配置读取失败:展示失败原因和文件名。 + +## 5. Agent 对话页 + +路径:`/chat//` + +页面区域: + +- 场景摘要:名称、角色、目标、RAG 状态、工具列表。 +- 文档范围:当前场景下状态为 `indexed` 的文档多选框;未选择时默认使用全部已入库文档。 +- 输入区:一个 textarea 和提交按钮。 +- 结果区:自然语言回答和结构化输出。 +- 引用区:source、chunk_id、score、content。 +- 工具区:tool_name、success、arguments、result、error。 +- 审计入口:当前对话生成日志后展示详情链接。 + +POST 成功后仍渲染同一页面,保留用户问题和 AgentResult。 + +## 6. 文件上传页 + +路径:`/documents/upload/` + +页面元素: + +- 场景选择下拉框。 +- 文件选择控件。 +- 支持类型提示。 +- 上传按钮。 +- 错误或成功提示。 + +表单接受 `.txt`、`.md`、`.pdf`、`.docx`。PDF 仅要求纯文本抽取,DOCX 仅要求段落和普通文本抽取。 + +## 7. 文件列表页 + +路径:`/documents/` + +展示字段: + +- 原始文件名。 +- 所属场景。 +- 文件类型。 +- 文件大小。 +- 入库状态。 +- 上传时间。 +- 入库按钮。 +- 失败原因。 + +状态为 `indexed` 时可以显示“重新入库”,重新入库需要覆盖或清理该文档旧 chunk。 + +## 8. 审计日志列表页 + +路径:`/audit/` + +展示字段: + +- 日志 ID。 +- 场景名称。 +- 用户输入摘要。 +- 状态。 +- 模型名称。 +- 执行耗时。 +- 创建时间。 +- 详情入口。 + +默认按 `created_at desc` 排序。 + +## 9. 审计日志详情页 + +路径:`/audit//` + +展示内容: + +- 场景信息。 +- 用户输入。 +- 最终回答。 +- 结构化输出 JSON。 +- RAG 引用列表。 +- 工具调用列表。 +- 模型名称和耗时。 +- 错误信息。 + +JSON 内容可以先用 `
` 展示,优先保证可读。
+
+## 10. Django Admin 页面
+
+Admin 注册:
+
+- `UploadedDocument`
+- `AgentAuditLog`
+- `DemoBusinessRecord`
+
+V1 不要求在 Admin 中编辑 YAML 场景,场景仍以配置文件为准。
+
+## 11. 页面跳转关系
+
+```text
+首页
+  |-- 进入对话页
+  |-- 文件列表页
+  |-- 审计日志列表页
+
+文件列表页
+  |-- 文件上传页
+  |-- 触发入库后回到文件列表页
+
+对话页
+  |-- 提交后留在当前对话页
+  |-- 查看当前审计详情
+
+审计列表页
+  |-- 审计详情页
+```
+
+## 12. 页面异常状态
+
+| 页面 | 异常 | 展示方式 |
+|---|---|---|
+| 首页 | 场景配置为空 | 空状态和配置目录说明 |
+| 对话页 | 场景不存在 | 明确提示并提供返回首页 |
+| 对话页 | Agent 执行失败 | 展示错误、保留输入、写入失败审计 |
+| 上传页 | 文件类型错误 | 表单错误 |
+| 文件列表 | 入库失败 | 状态为 failed 并显示原因 |
+| 审计详情 | 日志不存在 | 404 或友好错误页 |
+
+## 13. V1 页面验收标准
+
+- 主要页面可通过浏览器访问。
+- 页面之间跳转路径完整。
+- POST 表单使用 CSRF 保护。
+- 所有用户可见错误都有中文提示。
+- Agent 对话结果可以同时看到回答、引用、工具和审计入口。
+- 页面不依赖 React/Vue。
diff --git a/docs/设计文档/5.部署设计.md b/docs/设计文档/5.部署设计.md
new file mode 100644
index 0000000..dfaeb22
--- /dev/null
+++ b/docs/设计文档/5.部署设计.md
@@ -0,0 +1,103 @@
+# V1 部署设计文档
+
+## 1. 部署设计目标
+
+V1 部署目标是降低复试现场环境风险。系统应支持本地 Python 方式启动,也支持 Docker Compose 一键启动。默认不依赖外部数据库、Redis 或任务队列。
+
+## 2. 本地运行方式
+
+建议命令:
+
+```bash
+python -m venv .venv
+.venv\Scripts\activate
+pip install -r requirements.txt
+python manage.py migrate
+python manage.py runserver
+```
+
+本地运行使用 SQLite、`data/uploads` 和 `data/chroma`。
+
+## 3. Docker 运行方式
+
+建议命令:
+
+```bash
+docker compose up --build
+```
+
+V1 Docker Compose 只需要一个 Django Web 服务。Chroma 使用本地持久化目录,不额外启动独立服务。
+
+## 4. 环境变量设计
+
+| 变量 | 默认值 | 说明 |
+|---|---|---|
+| `DJANGO_SECRET_KEY` | `dev-secret-key` | 开发密钥 |
+| `DJANGO_DEBUG` | `true` | 是否开启调试 |
+| `DJANGO_ALLOWED_HOSTS` | `*` | 允许主机 |
+| `LLM_API_KEY` | 空 | 大模型 API Key |
+| `LLM_BASE_URL` | `https://api.openai.com/v1` | OpenAI 兼容接口地址,可接入 OpenAI、硅基流动等兼容服务 |
+| `LLM_MODEL` | `gpt-4.1-mini` | 默认模型 |
+| `EMBEDDING_API_KEY` | 空 | Embedding API Key;为空时可复用 `LLM_API_KEY` |
+| `EMBEDDING_BASE_URL` | 空 | Embedding OpenAI 兼容接口地址;为空时可复用 `LLM_BASE_URL` |
+| `EMBEDDING_MODEL` | `text-embedding-3-small` | 默认 Embedding 模型 |
+| `SCENARIO_CONFIG_DIR` | `configs` | 场景配置目录 |
+| `UPLOAD_ROOT` | `data/uploads` | 上传目录 |
+| `CHROMA_PATH` | `data/chroma` | 向量库目录 |
+
+`.env.example` 应提供这些变量的样例,不写真实密钥。
+
+## 5. 目录挂载设计
+
+Docker 需要持久化以下目录:
+
+```text
+./data/db.sqlite3
+./data/uploads
+./data/chroma
+./configs
+```
+
+`configs` 挂载后可以在不重建镜像的情况下修改场景配置。
+
+## 6. SQLite 数据持久化
+
+SQLite 文件放在 `data/db.sqlite3`。Docker 中应将 `data/` 作为 volume 挂载,避免容器重建后数据丢失。
+
+## 7. Chroma 数据持久化
+
+Chroma 数据放在 `data/chroma`。RAG 入库后,重启容器不应丢失向量数据。
+
+## 8. 上传文件持久化
+
+上传文件放在 `data/uploads//`。数据库只保存相对路径或 Django FileField 路径。
+
+## 9. 启动命令设计
+
+Docker 容器启动时建议执行:
+
+```bash
+python manage.py migrate
+python manage.py runserver 0.0.0.0:8000
+```
+
+V1 可以先用开发服务器满足演示。后续正式部署可切换到 Gunicorn。
+
+## 10. 常见部署问题
+
+| 问题 | 处理 |
+|---|---|
+| 端口 8000 被占用 | 修改 compose 端口映射 |
+| API Key 缺失 | 页面提示 LLM 或 Embedding 配置缺失 |
+| Chroma 目录无权限 | 检查 `data/chroma` 挂载权限 |
+| 上传目录不存在 | settings 或启动脚本创建目录 |
+| 场景配置读取失败 | 检查 `configs/*.yaml` 格式 |
+| Docker 构建慢 | 提前构建镜像或使用本地 Python 方式演示 |
+
+## 11. 后续部署扩展
+
+- 使用 Gunicorn + WhiteNoise。
+- 增加 PostgreSQL 服务。
+- 增加 Redis 和 Celery 做异步入库。
+- 增加 Nginx 反向代理。
+- 增加健康检查接口。
diff --git a/docs/设计文档/模块设计/1.配置模块详细设计.md b/docs/设计文档/模块设计/1.配置模块详细设计.md
new file mode 100644
index 0000000..4d4724e
--- /dev/null
+++ b/docs/设计文档/模块设计/1.配置模块详细设计.md
@@ -0,0 +1,106 @@
+# 配置模块详细设计
+
+## 1. 模块目标
+
+Config 模块负责 Django 项目的启动配置和总装配。它不承载业务逻辑,只为其他模块提供稳定运行环境。
+
+目标:
+
+- 项目本地和 Docker 均可启动。
+- 环境变量可覆盖关键配置。
+- App、模板、静态资源、上传文件和数据库路径统一配置。
+- URL 总入口清晰,模块路由各自维护。
+
+## 2. 职责边界
+
+负责:
+
+- `settings.py`、`urls.py`、`wsgi.py`、`asgi.py`。
+- 环境变量读取和默认值。
+- SQLite、静态文件、媒体文件、Chroma、场景配置目录。
+- Django Admin 和模块 URL 装配。
+
+不负责:
+
+- 不读取场景 YAML 业务内容。
+- 不调用 Agent Core。
+- 不处理上传文件文本抽取。
+- 不写审计日志。
+
+## 3. 配置项设计
+
+| 配置 | Django setting | 默认值 |
+|---|---|---|
+| `DJANGO_SECRET_KEY` | `SECRET_KEY` | `dev-secret-key` |
+| `DJANGO_DEBUG` | `DEBUG` | `true` |
+| `DJANGO_ALLOWED_HOSTS` | `ALLOWED_HOSTS` | `["*"]` |
+| `UPLOAD_ROOT` | `MEDIA_ROOT` | `BASE_DIR / "data" / "uploads"` |
+| `SCENARIO_CONFIG_DIR` | `SCENARIO_CONFIG_DIR` | `BASE_DIR / "configs"` |
+| `CHROMA_PATH` | `CHROMA_PATH` | `BASE_DIR / "data" / "chroma"` |
+| `LLM_API_KEY` | `LLM_API_KEY` | 空 |
+| `LLM_BASE_URL` | `LLM_BASE_URL` | `https://api.openai.com/v1` |
+| `LLM_MODEL` | `LLM_MODEL` | `gpt-4.1-mini` |
+| `EMBEDDING_API_KEY` | `EMBEDDING_API_KEY` | 空,默认可复用 `LLM_API_KEY` |
+| `EMBEDDING_BASE_URL` | `EMBEDDING_BASE_URL` | 空,默认可复用 `LLM_BASE_URL` |
+| `EMBEDDING_MODEL` | `EMBEDDING_MODEL` | `text-embedding-3-small` |
+
+## 4. 目录路径设计
+
+启动前或初始化时应确保:
+
+```text
+data/
+  uploads/
+  chroma/
+configs/
+static/
+templates/
+```
+
+V1 可以在 `settings.py` 中定义路径,在 management command 或启动脚本中创建目录。生产代码不应在每次请求中反复创建目录。
+
+## 5. URL 总路由设计
+
+`config.urls`:
+
+```python
+urlpatterns = [
+    path("admin/", admin.site.urls),
+    path("", include("apps.scenarios.urls")),
+    path("chat/", include("apps.chat.urls")),
+    path("documents/", include("apps.documents.urls")),
+    path("audit/", include("apps.audit.urls")),
+]
+```
+
+开发模式下追加 `static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)`,用于访问上传文件。
+
+## 6. 静态资源与上传文件设计
+
+- `STATIC_URL = "static/"`
+- `STATICFILES_DIRS = [BASE_DIR / "static"]`
+- `MEDIA_URL = "media/"`
+- `MEDIA_ROOT = UPLOAD_ROOT`
+
+上传文件路径由 Documents 模块按场景组织,Config 只提供根目录。
+
+## 7. 环境变量读取设计
+
+V1 可使用标准库 `os.environ.get()`,不强制引入复杂配置库。
+
+布尔值规则:
+
+```text
+"1", "true", "yes", "on" -> True
+其他 -> False
+```
+
+`DJANGO_ALLOWED_HOSTS` 使用逗号分隔,空值时默认 `["*"]`。
+
+## 8. 验收标准
+
+- `python manage.py check` 通过。
+- `python manage.py migrate` 可执行。
+- `/`、`/admin/` 路由可访问。
+- `MEDIA_ROOT`、`CHROMA_PATH`、`SCENARIO_CONFIG_DIR` 在 settings 中可被其他模块引用。
+- LLM 与 Embedding 配置只从 settings 或环境变量读取,不散落在业务代码中。
diff --git a/docs/设计文档/模块设计/2.场景模块详细设计.md b/docs/设计文档/模块设计/2.场景模块详细设计.md
new file mode 100644
index 0000000..a8c8bee
--- /dev/null
+++ b/docs/设计文档/模块设计/2.场景模块详细设计.md
@@ -0,0 +1,134 @@
+# 场景模块详细设计
+
+## 1. 模块目标
+
+Scenarios 模块是业务 Agent 的入口,负责读取和展示场景配置,并向 Chat、Documents、Agent Core 提供场景上下文。
+
+## 2. 职责边界
+
+负责:
+
+- 从 `configs/*.yaml` 读取场景。
+- 校验场景必填字段。
+- 展示场景列表和场景摘要。
+- 提供 `list_scenarios()`、`get_scenario()` 等服务。
+
+不负责:
+
+- 不执行 Agent。
+- 不做 RAG 检索。
+- 不调用工具和大模型。
+- 不保存审计日志。
+
+## 3. 场景配置结构
+
+必填结构:
+
+```yaml
+id: knowledge_qa
+name: 知识库问答助手
+description: 用于 SOP、制度和内部知识库问答
+applicable_questions:
+  - SOP 问答
+  - 制度问答
+
+agent:
+  role: 知识库问答专家
+  goal: 基于知识库回答用户问题
+  system_prompt: ""
+  instructions:
+    - 回答必须基于检索内容
+
+rag:
+  enabled: true
+  collection: knowledge_qa
+  top_k: 5
+
+tools:
+  - generate_action_items
+
+output:
+  type: general_answer
+
+audit:
+  enabled: true
+```
+
+`agent.system_prompt` 为可选字段。配置了非空值时,Agent Core 优先使用该字段作为系统提示词;为空或缺失时,由 `role`、`goal` 和 `instructions` 组合生成系统提示词。
+
+`applicable_questions` 作为页面展示字段,若缺失可显示为空列表。
+
+## 4. 场景加载流程
+
+1. 读取 `settings.SCENARIO_CONFIG_DIR`。
+2. 遍历 `.yaml` 和 `.yml` 文件。
+3. 使用 YAML parser 转为 dict。
+4. 调用 `validate_scenario()`。
+5. 转换为 `ScenarioConfig` dataclass 或普通 dict。
+6. 按文件名或配置顺序返回。
+
+为了便于复试修改,V1 不需要强缓存;若加缓存,应提供清理方式或在 DEBUG 下禁用缓存。
+
+## 5. 场景校验规则
+
+必填字段:
+
+- `id`
+- `name`
+- `description`
+- `agent.role`
+- `agent.goal`
+- `agent.instructions`
+- `rag.enabled`
+- `tools`
+- `output.type`
+- `audit.enabled`
+
+校验失败时返回包含文件名、字段路径、错误原因的结果。列表页可以跳过非法场景并展示错误摘要。
+
+## 6. 页面设计
+
+首页路径:`/`
+
+展示:
+
+- 场景名称。
+- 场景描述。
+- 适用题型。
+- RAG 是否启用。
+- 工具数量。
+- 进入对话按钮。
+
+可选详情页:`/scenarios//`。V1 可以把详情合并到 Chat 页面。
+
+## 7. 服务函数设计
+
+```python
+def list_scenarios() -> list[ScenarioConfig]:
+    """读取配置目录中的合法场景,非法场景以错误摘要返回给页面。"""
+
+def get_scenario(scenario_id: str) -> ScenarioConfig:
+    """按场景 ID 返回完整配置,找不到时抛出 ScenarioNotFound。"""
+
+def validate_scenario(config: dict) -> ValidationResult:
+    """校验必填字段、字段类型、工具名称和输出类型。"""
+```
+
+`get_scenario()` 找不到时抛出业务异常,例如 `ScenarioNotFound`,由 View 转成中文错误提示。
+
+## 8. 异常处理
+
+| 异常 | 处理 |
+|---|---|
+| 配置目录不存在 | 返回空列表和错误提示 |
+| YAML 语法错误 | 标记该文件无效 |
+| ID 重复 | 保留第一个,报告重复错误 |
+| 必填字段缺失 | 标记该场景无效 |
+| 工具不存在 | 场景仍可展示,但 Chat 执行时记录工具错误 |
+
+## 9. 验收标准
+
+- 首页至少展示 5 个场景。
+- 场景配置来自 `configs/` 文件。
+- 非法配置有明确错误,不导致首页 500。
+- Chat 可通过 `scenario_id` 获取完整配置。
diff --git a/docs/设计文档/模块设计/3.文档模块详细设计.md b/docs/设计文档/模块设计/3.文档模块详细设计.md
new file mode 100644
index 0000000..4f34e05
--- /dev/null
+++ b/docs/设计文档/模块设计/3.文档模块详细设计.md
@@ -0,0 +1,127 @@
+# 文档模块详细设计
+
+## 1. 模块目标
+
+Documents 模块让用户把复试题材料快速变成 Agent 可检索的知识库。V1 必须支持 `.txt`、`.md`、`.pdf` 和 `.docx`,保证常见复试材料可以进入 RAG。
+
+## 2. 职责边界
+
+负责:
+
+- 文件上传表单和页面。
+- 文件保存与元数据记录。
+- 读取文本内容。
+- 调用 Agent Core RAG 入库。
+- 更新入库状态。
+
+不负责:
+
+- 不实现向量检索算法。
+- 不生成模型回答。
+- 不直接写审计日志。
+
+## 3. 数据模型设计
+
+模型:`UploadedDocument`
+
+字段见 `docs/设计文档/3.数据库设计.md`。
+
+常量:
+
+```python
+STATUS_UPLOADED = "uploaded"
+STATUS_INDEXED = "indexed"
+STATUS_FAILED = "failed"
+SUPPORTED_EXTENSIONS = {".txt", ".md", ".pdf", ".docx"}
+```
+
+文件保存路径建议:
+
+```text
+uploads///_
+```
+
+## 4. 文件上传流程
+
+1. GET `/documents/upload/` 渲染上传表单。
+2. POST 校验 `scenario_id` 和文件。
+3. 调用 Scenarios 服务确认场景存在。
+4. 校验扩展名和文件大小。
+5. 保存文件。
+6. 创建 `UploadedDocument(status="uploaded")`。
+7. 跳转文件列表页并展示成功提示。
+
+## 5. 文本抽取流程
+
+抽取函数:
+
+```python
+def extract_text(document: UploadedDocument) -> str:
+    """按文件类型抽取可入库纯文本,失败时抛出可展示的业务异常。"""
+```
+
+规则:
+
+- `.txt`:优先 UTF-8,失败时尝试系统默认编码。
+- `.md`:UTF-8 读取,保留标题、列表和正文。
+- `.pdf`:抽取纯文本,不要求 OCR、表格还原和复杂版式理解。
+- `.docx`:抽取段落、标题和普通表格文本,不要求完整保留 Word 样式。
+- 空文本视为失败。
+- 文件不存在视为失败。
+
+XLSX 暂不作为 V1 必须项,可作为后续结构化业务数据导入能力。
+
+## 6. RAG 入库触发流程
+
+POST `/documents//index/`
+
+1. 获取 `UploadedDocument`。
+2. 调用 `extract_text()`。
+3. 调用 `agent_core.rag.ingest.ingest_document()`,传入 `document_id`、`scenario_id`、文件名和抽取文本。
+4. 成功后更新 `status="indexed"`,清空 `error_message`。
+5. 失败后更新 `status="failed"`,写入 `error_message`。
+6. 重定向回文件列表页。
+
+入库动作必须使用 POST,避免 GET 触发写操作。
+
+已入库或失败文档允许重新入库。重新入库前需要按 `document_id` 清理或覆盖旧 chunk,避免重复检索。
+
+## 7. 页面设计
+
+文件列表页展示:
+
+- 文件名。
+- 场景 ID。
+- 文件类型。
+- 文件大小。
+- 状态。
+- 上传时间。
+- 入库按钮。
+- 错误信息。
+
+上传页展示:
+
+- 场景下拉框。
+- 文件控件。
+- 支持类型提示。
+- 表单错误。
+
+## 8. 异常处理
+
+| 异常 | 处理 |
+|---|---|
+| 场景不存在 | 表单错误 |
+| 文件为空 | 表单错误 |
+| 扩展名不支持 | 表单错误 |
+| 文件保存失败 | 页面提示失败 |
+| 文本为空 | 状态 failed |
+| RAG 入库失败 | 状态 failed 并保存原因 |
+
+## 9. 验收标准
+
+- 可以上传 `.txt`、`.md`、`.pdf` 和 `.docx`。
+- 文件列表可看到记录。
+- 文件可按场景关联。
+- 入库成功状态变为 `indexed`。
+- 入库失败状态变为 `failed` 且可查看原因。
+- 入库失败或已入库文档可重新入库。
diff --git a/docs/设计文档/模块设计/4.对话模块详细设计.md b/docs/设计文档/模块设计/4.对话模块详细设计.md
new file mode 100644
index 0000000..a92680b
--- /dev/null
+++ b/docs/设计文档/模块设计/4.对话模块详细设计.md
@@ -0,0 +1,118 @@
+# 对话模块详细设计
+
+## 1. 模块目标
+
+Chat 模块负责复试演示中的主交互:用户选择场景后提交问题,系统展示 Agent 输出、引用、工具调用和审计入口。
+
+## 2. 职责边界
+
+负责:
+
+- 对话页 GET/POST。
+- 用户输入表单校验。
+- 获取场景配置。
+- 调用 Agent Core。
+- 调用 Audit 服务写日志。
+- 渲染 AgentResult。
+
+不负责:
+
+- 不直接读取 YAML。
+- 不直接调用 LLM。
+- 不直接执行 RAG 和工具。
+- 不实现复杂多轮会话状态。
+
+## 3. 页面设计
+
+路径:`/chat//`
+
+GET:
+
+- 加载场景配置。
+- 展示场景摘要。
+- 加载当前场景下状态为 `indexed` 的文档列表。
+- 展示空表单。
+
+POST:
+
+- 校验输入。
+- 执行 Agent。
+- 写审计。
+- 展示结果和审计链接。
+
+## 4. 表单设计
+
+字段:
+
+| 字段 | 类型 | 规则 |
+|---|---|---|
+| `message` | textarea | 必填,最大 4000 字 |
+| `document_ids` | 多选 | 可选,只能选择当前场景下已入库文档 |
+
+错误提示:
+
+- 空输入:`请输入要咨询的问题。`
+- 超长输入:`问题过长,请控制在 4000 字以内。`
+- 文档不属于当前场景或未入库:`请选择当前场景下已入库的文档。`
+
+## 5. Agent Core 调用流程
+
+```python
+scenario = get_scenario(scenario_id)
+result = run_agent(
+    scenario_config=scenario,
+    user_input=form.cleaned_data["message"],
+    options={"document_ids": form.cleaned_data.get("document_ids", [])}
+)
+```
+
+Chat 只依赖 Agent Core 的统一返回对象,不关心内部是否使用 RAG、工具或真实模型。
+
+未选择文档时,`document_ids` 传空列表或不传,由 Agent Core 默认使用当前场景全部已入库文档。
+
+## 6. 结果展示设计
+
+优先级:
+
+1. 如果 `structured_output` 不为空,展示结构化 JSON 或字段化结果。
+2. 展示 `answer`。
+3. 展示 `references`。
+4. 展示 `tool_calls`。
+5. 展示 `latency_ms`、`model_name`、`status`。
+6. 如果有 `error`,展示中文错误提示。
+
+结构化解析失败时,页面仍展示 `raw_output` 或 `answer`。
+
+## 7. 审计日志写入流程
+
+Agent Core 返回后调用:
+
+```python
+audit_log = create_audit_log(
+    scenario_id=scenario.id,
+    scenario_name=scenario.name,
+    user_input=message,
+    agent_result=result,
+)
+```
+
+如果 Agent Core 抛异常,Chat 应构造失败结果并继续写失败审计。
+
+## 8. 异常处理
+
+| 异常 | 处理 |
+|---|---|
+| 场景不存在 | 显示错误并返回首页入口 |
+| 表单无效 | 留在页面并显示表单错误 |
+| Agent Core 抛异常 | 构造 failed AgentResult,写审计 |
+| 审计写入失败 | 页面提示审计失败,但展示 Agent 输出 |
+| LLM 配置缺失 | 展示模型配置缺失 |
+
+## 9. 验收标准
+
+- 从首页可进入对话页。
+- 可提交问题并渲染 AgentResult。
+- 可选择本次对话使用的文档范围;未选择时默认使用当前场景全部已入库文档。
+- 失败时有中文提示。
+- 成功和失败都尽量写入审计。
+- View 中没有 RAG、工具、LLM 的细节实现。
diff --git a/docs/设计文档/模块设计/5.审计模块详细设计.md b/docs/设计文档/模块设计/5.审计模块详细设计.md
new file mode 100644
index 0000000..886abea
--- /dev/null
+++ b/docs/设计文档/模块设计/5.审计模块详细设计.md
@@ -0,0 +1,121 @@
+# 审计模块详细设计
+
+## 1. 模块目标
+
+Audit 模块记录 Agent 执行过程,使演示者能够解释一次输出的来源、工具调用和模型结果。它是系统从“普通问答页面”变成“可追踪业务 Agent”的关键。
+
+## 2. 职责边界
+
+负责:
+
+- `AgentAuditLog` 模型。
+- 审计写入服务。
+- 审计列表页。
+- 审计详情页。
+- 敏感信息过滤。
+
+不负责:
+
+- 不执行 Agent。
+- 不执行 RAG。
+- 不执行工具。
+- 不调用模型。
+
+## 3. 数据模型设计
+
+模型:`AgentAuditLog`
+
+字段见 `docs/设计文档/3.数据库设计.md`。
+
+JSON 字段默认值必须使用函数,例如 `default=list`、`default=dict`,避免多实例共享同一对象。
+
+## 4. 日志写入流程
+
+服务函数:
+
+```python
+def create_audit_log(
+    scenario_id: str,
+    scenario_name: str,
+    user_input: str,
+    agent_result: AgentResult,
+) -> AgentAuditLog:
+    """将 AgentResult 映射为 AgentAuditLog,并在保存前做敏感信息脱敏。"""
+```
+
+写入映射:
+
+- `agent_result.references` -> `retrieved_chunks`
+- `agent_result.tool_calls` -> `tool_calls`
+- `agent_result.structured_output` -> `structured_output`
+- `agent_result.answer` -> `final_answer`
+- `agent_result.raw_output` -> `raw_output`
+- `agent_result.model_name` -> `model_name`
+- `agent_result.latency_ms` -> `latency_ms`
+- `agent_result.status` -> `status`
+- `agent_result.error` -> `error_message`
+
+## 5. 日志列表页设计
+
+路径:`/audit/`
+
+查询:
+
+- 默认按创建时间倒序。
+- V1 可不做分页,若日志较多再加 Django Paginator。
+
+展示:
+
+- ID。
+- 场景名称。
+- 用户输入前 80 字。
+- 状态。
+- 模型名。
+- 耗时。
+- 创建时间。
+- 详情链接。
+
+## 6. 日志详情页设计
+
+路径:`/audit//`
+
+展示:
+
+- 基础信息。
+- 用户输入。
+- 最终回答。
+- 结构化输出。
+- RAG 检索片段。
+- 工具调用。
+- 原始输出。
+- 错误信息。
+
+JSON 可用格式化后的 `
` 展示。
+
+## 7. 敏感信息处理
+
+不得保存:
+
+- `LLM_API_KEY`
+- 完整环境变量 dump
+- 用户机器上的敏感绝对路径
+- Docker secret 或 token
+
+如错误信息来自异常对象,应在保存前做简单脱敏,至少替换 API Key 值。
+
+## 8. 异常处理
+
+| 异常 | 处理 |
+|---|---|
+| AgentResult 字段缺失 | 使用默认空值 |
+| JSON 不可序列化 | 转为字符串或空对象 |
+| 日志不存在 | 返回 404 |
+| 写入失败 | 抛给 Chat,由 Chat 展示审计失败提示 |
+
+## 9. 验收标准
+
+- 每次对话成功后有审计日志。
+- Agent 失败也有失败日志。
+- 列表页可查看日志摘要。
+- 详情页可查看输入、输出、引用和工具调用。
+- 日志不包含 API Key。
diff --git a/docs/设计文档/模块设计/6.智能核心模块详细设计.md b/docs/设计文档/模块设计/6.智能核心模块详细设计.md
new file mode 100644
index 0000000..4854373
--- /dev/null
+++ b/docs/设计文档/模块设计/6.智能核心模块详细设计.md
@@ -0,0 +1,259 @@
+# 智能核心模块详细设计
+
+## 1. 模块目标
+
+Agent Core 提供独立于 Django View 的智能编排能力。它消费场景配置,执行 RAG、工具、模型调用和结构化解析,最终返回统一 AgentResult。
+
+## 2. 职责边界
+
+负责:
+
+- Agent 编排。
+- 场景配置对象消费。
+- RAG 入库和检索。
+- 工具注册与执行。
+- LLM Provider 与 Embedding Provider。
+- 结构化输出解析。
+- AgentResult 定义。
+
+不负责:
+
+- 不渲染页面。
+- 不处理 Django 表单。
+- 不保存 Django Model。
+- 不管理登录权限。
+
+## 3. 子模块划分
+
+```text
+agent_core/
+  orchestrator.py
+  scenario_loader.py
+  llm_provider.py
+  tool_registry.py
+  structured_output.py
+  rag/
+    ingest.py
+    retriever.py
+  tools/
+    builtin_tools.py
+  schemas/
+    outputs.py
+```
+
+`scenario_loader.py` 可作为非 Django 环境下加载配置的工具;Django 场景展示仍由 `apps.scenarios` 负责。
+
+## 4. Orchestrator 设计
+
+入口:
+
+```python
+def run_agent(scenario_config, user_input: str, options: dict | None = None) -> AgentResult:
+    """执行一次 Agent 编排,options 可包含 document_ids 等运行期约束。"""
+```
+
+流程:
+
+1. 记录开始时间。
+2. 根据 `rag.enabled`、`scenario_id` 和可选 `document_ids` 检索引用。
+3. 根据 `tools` 执行或准备工具结果。
+4. 构造 messages。
+5. 调用 LLM Provider。
+6. 解析结构化输出。
+7. 计算耗时。
+8. 返回 `AgentResult(status="success")`。
+9. 捕获可恢复异常并返回 `status="failed"`。
+
+V1 在缺少 LLM 或 Embedding 配置时必须返回清晰失败结果。测试代码可以使用 mock provider,但 V1 验收链路必须通过真实 OpenAI 兼容 LLM、Embedding 和 Chroma。
+
+## 5. Scenario Loader 设计
+
+Agent Core 的 Scenario Loader 用于脚本、测试或后续独立服务场景。它不依赖 Django View,可以复用 Scenarios 模块的字段规范。
+
+接口:
+
+```python
+load_scenario(path: str) -> dict
+load_scenarios(directory: str) -> list[dict]
+```
+
+## 6. RAG 设计
+
+入库接口:
+
+```python
+def ingest_document(
+    document_id: int,
+    scenario_id: str,
+    source_file: str,
+    text: str,
+    collection: str,
+) -> IngestResult:
+    """切分文档、生成 embedding,并写入 Chroma。重新入库时覆盖同一 document_id 的旧 chunk。"""
+```
+
+检索接口:
+
+```python
+def retrieve(
+    scenario_id: str,
+    query: str,
+    collection: str,
+    top_k: int = 5,
+    document_ids: list[int] | None = None,
+) -> list[ReferenceChunk]:
+    """按场景和可选文档范围执行向量检索,返回可审计引用片段。"""
+```
+
+切分策略:
+
+- 默认 chunk size 800 到 1000 字。
+- overlap 100 到 150 字。
+- metadata 包含 `scenario_id`、`document_id`、`source_file`、`chunk_id`。
+
+RAG 入库和检索必须使用 Embedding Provider 与 Chroma。单元测试桩或开发阶段临时验证方案不属于 V1 验收设计。
+
+## 7. Tool Registry 设计
+
+工具注册:
+
+```python
+registry.register("calculate_rate", calculate_rate)
+registry.get("calculate_rate")
+registry.run("calculate_rate", **kwargs)
+```
+
+工具结果统一:
+
+```json
+{
+  "tool_name": "calculate_rate",
+  "success": true,
+  "arguments": {},
+  "result": {},
+  "error": ""
+}
+```
+
+内置工具:
+
+- `calculate_rate`
+- `query_demo_records`
+- `check_required_fields`
+- `generate_action_items`
+
+工具函数不得直接读取 API Key 或执行无审计的外部副作用。
+
+## 8. LLM Provider 设计
+
+接口:
+
+```python
+class LLMProvider:
+    def generate(self, messages: list[dict], response_format: dict | None = None) -> LLMResponse:
+        """调用 OpenAI 兼容 Chat Completions 接口并返回统一响应对象。"""
+```
+
+配置来源:
+
+- `LLM_API_KEY`
+- `LLM_BASE_URL`
+- `LLM_MODEL`
+
+Provider 对外隐藏供应商差异,Orchestrator 只处理 `LLMResponse.content`、`LLMResponse.model_name` 和错误信息。供应商可自主选择 OpenAI、硅基流动等 OpenAI 兼容服务。
+
+Embedding Provider 接口:
+
+```python
+class EmbeddingProvider:
+    def embed_texts(self, texts: list[str]) -> list[list[float]]:
+        """调用 OpenAI 兼容 Embeddings 接口,返回与输入文本一一对应的向量。"""
+```
+
+配置来源:
+
+- `EMBEDDING_API_KEY`
+- `EMBEDDING_BASE_URL`
+- `EMBEDDING_MODEL`
+
+当 `EMBEDDING_API_KEY` 或 `EMBEDDING_BASE_URL` 为空时,可以复用 `LLM_API_KEY` 和 `LLM_BASE_URL`。
+
+## 9. Structured Output 设计
+
+接口:
+
+```python
+def parse_structured_output(raw_output: str, output_type: str) -> ParseResult:
+    """优先解析 JSON,并根据输出类型返回结构化结果或解析错误。"""
+```
+
+策略:
+
+- 优先解析 JSON。
+- 根据 `output_type` 做字段补齐或轻校验。
+- 失败时返回 `success=False`,保留 `raw_output`。
+- 不因结构化解析失败导致整个 Agent 流程崩溃。
+
+## 10. AgentResult 设计
+
+建议 dataclass:
+
+```python
+@dataclass
+class AgentResult:
+    answer: str
+    structured_output: dict
+    references: list
+    tool_calls: list
+    raw_output: str
+    model_name: str
+    latency_ms: int
+    status: str
+    error: str = ""
+```
+
+所有字段必须有默认值或构造时明确传入,保证 Audit 模块写入稳定。
+
+## 11. Adapter 扩展设计
+
+统一接口:
+
+```python
+class AgentEngine:
+    def run_agent(self, scenario_config, user_input: str, options: dict | None = None) -> AgentResult:
+        """保持与顶层 run_agent 函数一致的输入输出合约。"""
+```
+
+V1 实现:
+
+- `LightweightOrchestrator`
+
+后续扩展:
+
+- `DifyAdapter`
+- `OpenAIAgentsAdapter`
+- `LangGraphAdapter`
+
+Adapter 只能替换编排实现,不能改变 Django 层依赖的 AgentResult 合约。
+
+## 12. 异常处理
+
+| 异常 | 处理 |
+|---|---|
+| RAG 检索失败 | 记录错误,允许继续或返回 failed |
+| 工具不存在 | 记录失败工具调用 |
+| 工具执行异常 | 捕获并返回失败工具结果 |
+| LLM 配置缺失 | 返回 failed AgentResult |
+| LLM 调用失败 | 返回 failed AgentResult |
+| JSON 解析失败 | 返回 success 但带解析错误,展示 raw output |
+
+## 13. 验收标准
+
+- Chat 可以调用 `run_agent()`。
+- 返回对象字段稳定完整。
+- RAG 按 `scenario_id` 隔离。
+- RAG 支持按 `document_ids` 限定本次对话的文档范围。
+- 工具调用结果格式统一。
+- LLM 与 Embedding 配置从环境变量读取。
+- 结构化解析失败不导致页面崩溃。
+- Agent Core 不依赖 Django View。