这不是框架选型报告。它只回答项目内部四件事:一次提问怎么跑完、MAF 在其中做什么、Agent / Skill / Tool / Workflow 如何配合、继续开发 MVR 应该改哪里。所有结论来自当前代码与 235 运行数据库。
PIKE-RAG 自己定义 MVR 角色、技能、检索工具、知识库、模型路由与前端协议;MAF 负责把这些东西装成一个可运行的 Agent,并管理会话、工具调用循环、流式输出与请求内 Workflow。把这条边界看清,后面才知道新增功能应该落在哪一层。
MAF = Agent Runtime。它接收系统指令、历史消息、Skills、Tools 与模型客户端,创建 ChatClientAgent,让模型在“思考 → 调工具 → 接收结果 → 再思考 → 输出答案”的循环里运行。MVR 的医药规则、知识检索与引用格式都不是 MAF 内置能力,而是 PIKE-RAG 注入进去的业务能力。
mvr-pharma、知识库与文档范围,输入问题;页面持续接收答案、处理状态、工具轨迹、引用和 Token 用量。Agents.cs 校验请求,解析草稿或发布路由,补默认 KB / Pool,生成 runId,把运行结果交给 SSE Writer。AITool,设置模型参数、历史、上下文与运行归因字段。PoolRoutingChatClient 从 ChatOptions.AdditionalProperties.poolId 选择 Backend,把 MAF 的标准 IChatClient 调用路由到实际 LLM,并记录延迟、Token 与完整调用 Trace。kb_search 调 Embedding Pool 生成查询向量,Milvus 做 Dense / Sparse / Hybrid 召回,再按配置调用 Reranker,返回带文档与 chunk 元数据的证据。status / trace / delta / references / completed,再持久化会话与运行 Trace。ChatClientAgent、Session、RunStreamingAsyncAgent Session;请求体 history 注入 InMemory History,再应用 Sliding Window CompactionAgentSkillsProviderBuilder、load_skill、资源加载WorkflowBuilder、Executor、条件边、InProcessExecution下面按真实执行顺序走一遍。橙色步骤属于 PIKE-RAG 业务代码,蓝色步骤由 MAF 运行,绿色步骤进入知识与模型基础设施。MAF 的核心价值不是生成医学知识,而是让这些步骤在一个稳定的 Agent 循环里自动衔接。
页面从 Agent 关联关系中取默认 KB,把问题、knowledgeBaseId、文档范围、历史消息与 sessionId 发到 /api/v3/agentic/agents/mvr-pharma/playground/chat/completions。
Agents.cs 读取 mvr-pharma 草稿态数据,补上当前默认 KB 与 lmstudio-chat Pool,生成唯一 runId,构造 TargetRunCommand。
kb-context 把空文档范围转为 ["*"],或把重复文档归一到 owner;kb-validation 确认 KB 存在。失败会在 Agent 启动前短路,不浪费一次 LLM 调用。
版本化 Skill 被转换为 AgentInlineSkill;每个 IConfigurableTool 读取当前配置与 KB 上下文,再通过 AIFunctionFactory.Create 变成模型可见的函数定义。
MAF 接收系统提示词、Tools、Skill Context、温度、Token 上限和请求体显式回传的历史。每个 HTTP 请求都会新建 MAF Session;业务 sessionId 只用于会话持久化,不会恢复 MAF Session。历史超过阈值时再执行滑动窗口压缩。
PoolRoutingChatClient 从 poolId 选择当前模型 Backend。模型看到 MVR 系统规则与 Skill 广告后,不直接回答,而是先发出 load_skill("mvr-knowledge-qa")。
MAF 执行 load_skill,把技能指令放回上下文;模型按技能要求先拆任务,再调用中文与英文 kb_search、术语查询、文档发现或章节阅读。每个 tool result 都会自动回填到下一次模型调用。
查询先经过术语展开;Embedding Pool 生成查询向量;Milvus 执行 Hybrid 召回;当前配置先取 30 条候选,再由 Reranker 精排并按 0.3 阈值过滤,最终最多返回 8 条带来源元数据的证据。
mvr-knowledge-qa 完成一轮后加载 mvr-replan。证据主题偏离或上下文不全时,模型提出新的 query 再进入检索;证据充分或达到强制终止条件后,加载 mvr-grounded-answer。
答案必须先给 summary,再按主题组织正文;事实必须来自检索证据并带 [N];结尾输出 references JSON。这里定义的是 MVR 合规回答契约,不是 MAF 默认格式。
MAF 输出的 reasoning、文本、FunctionCallContent、FunctionResultContent 和 UsageContent 被转换为 thinking / delta / trace / status。前端可以一边显示答案,一边显示“正在检索知识库”。
CitationPostProcessor 把 references 围栏解析成结构化引用;再从 Milvus 回填完整 chunk,并补充重复文档 ID。AgentSseWriter 发送 references 与 completed,最后保存 Chat History、Trace 和调用用量。
拆分问题,执行中英文检索、术语确认、文档发现与上下文扩展。
判断资料是否覆盖全部信息需求;不足时给出具体补充方向。
证据充分后生成摘要、正文与结构化引用,禁止使用库外知识。
在这个项目里,Agent、Skill、Tool、KB、Processor、Pool、Workflow 各自只做一件事。MVR 的能力来自它们的组合,而不是某一个超长 Prompt。开发时先判断需求属于哪个组件,再改对应层。
业务角色与运行容器。决定系统指令、模型 Pool、Skills、Tools、KB、迭代上限和前后处理器。
模型的工作说明书。告诉模型何时加载、如何分解问题、允许调用哪些工具、怎样判断充分、最终怎样输出。
可执行动作。输入有 Schema,执行 C# 代码,返回模型可读结果;如搜索、术语查询、读文档和取目录。
证据范围。决定可检索文档、Embedding 模型与 Milvus collection;MVR 的事实边界最终由这里决定。
Agent 循环外的确定性护栏。Pre 先校验 KB 与文档;Post 把模型输出解析为结构化引用并回填完整证据。
模型路由与运行归因。Agent 只写 poolId,Gateway 决定真正打哪个 Backend,并记录 Token、延迟、Agent 与 KB。
确定步骤与顺序。适合必须按固定阶段运行、需要条件分支,或需要持久化、暂停恢复的流程。项目里有 MAF AI Workflow 与 Elsa Workflow 两类。
mvr-pharma 是一个 Agent 模式的业务入口。系统提示词负责意图边界,4 个 Skill 负责策略,6 个 Tool 负责执行,默认 KB 负责证据范围,lmstudio-chat 负责模型,两个 PreProcessor 负责运行前门禁,Citation PostProcessor 负责运行后结构化。MAF 把这些对象连接成一个可多轮调用工具的 ChatClientAgent。
| 需要理解的对象 | 当前 MVR 实现 | 它如何参与一次回答 |
|---|---|---|
| Agent System Prompt | Definitions/agents/mvr-pharma/v1.agent.yaml | 禁止直接回答;业务问题必须先加载 mvr-knowledge-qa;纯闲聊才加载 chitchat。 |
| Skill 选择 | mvr-knowledge-qa / mvr-replan / mvr-grounded-answer / mvr-chitchat | 模型通过 MAF 的 load_skill 动态加载,而不是一次把所有长指令塞进系统提示词。 |
| Tool 执行 | kb_search / discover / facets / read / outline / lookup_term | MAF 产生 function call;PIKE-RAG 执行 C# 工具;结果回到 MAF 下一轮。 |
| 检索策略 | kb_search: top_k=8, initial_recall=30, rerank=true, threshold=0.3 | 先扩大召回,再精排收缩;Skill 决定查什么,Tool Config 决定怎样查。 |
| 上下文 | 默认 KB + documentIds + history | PreProcessor 把文档范围写入 ToolContext;MAF History Provider 管理会话消息。 |
| 最终输出 | summary + Markdown + references JSON | Skill 规定格式;PostProcessor 解析引用;SSE 与历史存储保存结构化结果。 |
项目按任务生命周期选择运行形态:Agent 负责由模型动态决定下一步;MAF AI Workflow 负责一次请求内的固定图编排;Elsa Workflow 负责跨分钟或跨小时、需要持久化、重试、暂停恢复的业务流程。三者可以围绕同一个知识库协作。
先判定业务问答还是闲聊;禁止跳过 Skill 直接回答。
模型选择 Skill 与 Tool,MAF 执行并把结果回填,直到输出最终答案。
查询次数、中文/英文组合、文档阅读深度由模型依据证据动态决定。
PIKE-RAG 解析 references,并以 SSE 与历史记录返回。
确定 KB 存在并读取 Embedding 配置。
把文档分成可用、处理中、缺失,并在无可用文档时短路。
检索 → 充分性判断 → 新 query;最多按参数执行 N 轮。
流式生成答案,构造引用并统计 Token。
IWorkflowDispatchService 创建 WorkflowRun,经 Hangfire 派发。
Elsa 在 PostgreSQL 保存实例、活动日志、输入输出与关联 ID。
适合文档入库、批量评测、人工审批等长任务。
Workflow Activity 可像 EvaluateSingleItemActivity 一样调用 AgentFactory。
先由 Elsa Workflow 准备数据:上传文档后执行 lake → warehouse → vector,把可检索证据写入 Milvus。再由 MAF Agent 使用数据:MVR 对话通过 Tool 检索同一个 KB。最后由 Elsa eval_run 批量验收 Agent:评测 Activity 调用 AgentFactory,内部仍由 MAF 执行对话,再把准确性、完整性、groundedness、延迟与 Token 汇总为可追踪结果。
下一步依赖模型对证据的判断,工具次数不固定。使用 Agent Loop。
必须先校验、再门禁、再循环检索、最后生成;整个请求内完成。使用 MAF AI Workflow。
需要持久化、暂停恢复、审批、批量处理或失败重试。使用 Elsa Workflow,步骤内可调用 Agent。
下面不是设计稿,而是 2026-07-22 从 235 PostgreSQL 读取的 mvr-pharma 实际绑定。它解释了为什么 Playground 能跑,也解释了继续开发前必须先统一哪些配置来源。
agent_mode=agentworkflow_id=nullkb_707811d90aa3426191c95YAML 内置定义是代码仓库里的长期来源;数据库草稿态是 Playground 当前读取的可编辑状态;Revision / Publication保存准备对外调用的版本快照。当前 mvr-pharma 没有 active release binding,因此演示与验证走 /playground/chat/completions。发布运行链还需要补一处:当前 endpoint 解析了已发布 Pool / KB / Workflow,但 AgentFactory 仍按名称读取 live DB 的系统提示词、Skills 与 Tools;第一次正式发布前应让 Factory 直接执行 runtime_spec_json。
v1.agent.yaml 当前仍写 poolId: default,且没有声明 knowledgeBases。4 个 Skill 与 6 个 Tool 在这里定义。
数据库已经人工绑定 lmstudio-chat 与真实 KB,所以 Playground 能运行。AgentFactory.LoadAgentDefinitionAsync 当前优先读取这份数据库状态。
内置 Agent Revision B1 状态为 verified,快照中的 Pool 仍是 default。正式发布前应先把长期配置对齐,再生成新版本。
db-init / Migrator 会执行 BuiltinAgentSyncService;内置 Agent 默认 syncPolicy=always,会用 YAML 同步 Pool、Skills、Tools 与 KB 关联。
当前同步服务在 spec hash 变化时会更新已有 B 前缀 revision。正式开发前应先生成独立 U revision / publication,或先把内置同步改为按每个 YAML 版本生成不可变快照。
Playground 继续读取 live DB;发布路由应把 runtime_spec_json 整体交给运行器,而不是只传 Pool / KB / Workflow 后再加载 live Agent。
| 状态层 | 主要代码 / 表 | 什么时候生效 |
|---|---|---|
| 内置源 | Definitions/agents + Definitions/skills | 编译为 embedded resource;db-init / Migrator 同步到数据库并生成 B 前缀 revision。 |
| 草稿态 | agent / agent_skill / agent_tool / agent_knowledge_base | Playground 和 /{identifier}/completions 通过 AgentFactory 读取。 |
| Skill 版本 | skill_revision + agent_skill.version_spec | SkillSpecResolver 按 B1 / B2 / latest 解析为运行快照。 |
| 发布态 | agent_revision / agent_publication / agent_release_binding | 创建 publication 后公开路由才有 active route;当前还需把完整 runtime snapshot 接入 AgentFactory 才能真正隔离 live 草稿。 |
| 运行追踪 | agent_trace_run / agent_trace_step / agent_llm_call | 每次带 runId 的调用记录 prompt、模型、工具、结果、Token 与耗时。 |
继续做 MVR 时,不要默认“再加一个 Agent”。回答质量通常改 Skill;需要新动作才加 Tool;步骤必须固定才加 MAF AI Workflow;需要持久化、批处理或人工审批才加 Elsa Workflow。下面四条路径覆盖最常见的开发任务。
适用于“检索不够准、少搜了英文、回答漏要点、摘要格式不稳、引用不完整”。这类需求不需要新增 Agent,也不需要先写 Workflow。
mvr-pharma;检索策略改 mvr-knowledge-qa;是否继续搜改 mvr-replan;答案与引用格式改 mvr-grounded-answer。v2.skill.yaml 并把 Agent 绑定指向新版本。当前 Builtin Sync 会在 hash 变化时更新已有 B revision;若要保证 B1 不变,需要先修正同步策略或使用独立 U revision。kb_search config:top_k / initial_recall / rerank_enabled / rerank_threshold,无需改 MAF。mvr-pharma Playground 验完整 Skill Loop。适用于“查询结构化药品主数据、检查禁忌规则、生成合规编号、调用审批系统”。Tool 是可测试的 C# 能力,Skill 只负责告诉模型何时以及怎样调用。
IConfigurableTool 的类,定义 ToolName / Description / GetConfigSchema / GetParameterSchema / ExecuteAsync。ToAIFunction 中用 AIFunctionFactory.Create 把强类型参数与 CancellationToken 转成函数 Schema;失败返回稳定错误码,不返回 null。DependencyInjection.cs 注册具体类型与 IConfigurableTool;将 Tool 加入 Agent YAML,并通过 Tool Config 设置全局或 Agent 级参数。allowedTools 与 instructions 中写清触发条件、参数来源、失败处理和禁止事项,避免模型看到工具却不知道何时调用。/agentic/tools/{tool}/completions 单测,再走 Skill,最后走 MVR Agent;验 FunctionCallContent、Tool Result、Trace 与最终答案。例如把“回答一个问题”升级成“收集需求 → 检索证据 → 生成 MVR 草稿 → 规则审查 → 人工确认 → 发布版本”。这已经不是单纯 Prompt 调整,应显式建流程。
IAiWorkflowDefinition,使用 MAF Workflows。需要人工审批、数小时等待、失败重试或批量文档:使用 Elsa Workflow。ValidateInput → ResolveScope → CollectEvidence → DraftSections → ComplianceCheck → HumanApproval → Finalize。每个节点定义输入、输出、失败码与 Trace。MvrWritingWorkflow : IAiWorkflowDefinition、注册 DI、扩展 BuiltinAiWorkflowSyncService。若 Workflow 由 Agent 自主选择,需要把 RunAsToolAsync 包成 AITool 注入 AgentFactory;若直接接管请求,只需绑定 workflow_id。Elsa 路径新增 Activities 与 mvr-writing.workflow.yaml。status / trace / delta / references / completed;前端无需理解每个内部类,只按统一事件渲染进度和产物。MVR 变更不能只以“Playground 能回答”结束。项目已经有 Revision、Evaluation、Publication 与 Rollback 数据模型,应把它们串成固定发布门。
default 或清掉 KB。eval_run 加载数据集,逐条调用 AgentFactory。本地规则验内容、关键词、工具与引用;LLM / Foundry 评相关性、准确性、完整性、groundedness。agent_publication 并更新 agent_release_binding.current_publication_id;验收公开调用使用 snapshot 中的 Prompt / Skills / Tools / KB,而不是发布后修改的草稿。先做 配置与版本收口:把 mvr-pharma 的长期 Pool、默认 KB、4 个 Skill 绑定与当前 235 运行态对齐;修正内置 Revision 的不可变策略;让 published route 执行完整 snapshot;建立回归数据集并发布第一个 active publication。完成这个基线后,再开发结构化 MVR Writing Workflow。
| 开发目标 | 主要文件 | 验收入口 |
|---|---|---|
| 修改 MVR 角色 | Definitions/agents/mvr-pharma/vN.agent.yaml | Agent Playground · 意图路由 · 安全规则 · max iterations |
| 修改检索策略 | Definitions/skills/mvr-knowledge-qa/vN.skill.yaml | Skill Playground · 中英双检索 · 深挖与重试 |
| 修改充分性判断 | Definitions/skills/mvr-replan/vN.skill.yaml | 缺证据案例 · 主题偏离案例 · 最大重规划次数 |
| 修改答案格式 | Definitions/skills/mvr-grounded-answer/vN.skill.yaml | summary · 引用 · 术语规范 · 忠实性 |
| 增加业务动作 | Infrastructure/Services/*Tool.cs + DependencyInjection.cs | Tool → Skill → Agent 三层测试 |
| 修改 RAG 行为 | KbSearchTool.cs + tool_configuration | 召回数 · Rerank · 阈值 · 失败码 · Trace |
| 请求内固定流程 | Application/AiWorkflows/Builtin/*Workflow.cs | /agentic/ai-workflows/{name}/completions |
| 长流程 / 审批 | Workflows/Activities + Workflows/Definitions/*.workflow.yaml | WorkflowRun · suspend/resume · 审批记录 · 失败重试 |
| 模型路由 | Pike.AiGateway/PoolRoutingChatClient.cs + llm_pool/backend | Chat tools · SSE · Token · Backend health |
| 流式前端 | AgentSseWriter.cs + ConversationPanel/index.tsx | status · trace · delta · references · completed |
| 质量评测 | Evaluation/* + eval-run.workflow.yaml | 本地规则 + LLM Judge + Foundry 五维指标 |
| 版本发布 | AgentRelease.cs + PublishAgentCommandHandler.cs | revision → publication → published endpoint → rollback |