药材谷 · 底座十层详解(实扫真版)

每一层:有什么功能 + 我方真实怎么实现(真文件 / 真端点 / 真代码)+ 输入怎么进 + 输出怎么快
实扫取证 · 59 条证据 给 K3 照抄版 不设时间 · 持续推进
怎么用这份:这不是伪代码,是我方底座正在跑的真东西。每层都标了真实文件路径与真实机制,K3 照着自己搭,哪块卡就问哪块。三件你点名要的重点(记忆 / 调度 / 输出流式)单独成型在第五、六、七节,带可直抄的真代码。

〇、十层速查表(我方实况)

层名字干什么我方真实实现(文件 / 端点)状态
10前端层对话界面 + 流式渲染本草大脑_v149/frontend/index.html · getReader 流式有
9会话 / 记忆层多轮 + 长短记忆routers/chat.py 会话表 + plugins/memory_layers.py 五层记忆有(超配)
8API 网关统一入口 / 鉴权 / 限流 / SSE8979(916 端点)+ 8981(144 端点)· _bre_hits 限流有
7Agent 编排调度:想 → 派活 → 执行 → 答agents.py route_intent/swarm + plugins/leader.py + 蜂群调度中枢超配
6工具层查行情 / 识药 / 煎药 / 配伍…名册 gen-164 · 165 台 + ask 带参 + federate 联邦超配
5RAG 检索找知识 + 门槛拒答166 个 bre/*.py 规则引擎 + herbs/search · prescriptions/search部分(向量未接)
4数据层语料库 + 向量管道种子种苗档案 + backend/kg/ 本体 + 采集蜂 20 表 + 护栏库有
3微调层自有模型train/ lora+dpo+评测全套 · yaocai-q4-v5 已入 ollama有(超配)
2模型层出答案的脑子6 模型:qwen2.5:7b / qwen2.5vl:7b / yaocai-q4-v5 / bge-m3有
1基础设施推理 / 存储 / 服务ollama 11434 自部署 + MariaDB 3307 + 80/8979/8981 三服务有

★ 一句话:十层我方 8 层齐、其中 3 层是超配(K3 图纸没有的咱有);真缺口只有 ① 向量检索管道(pgvector/bge-m3 已备、未接)② 前端 Markdown / 代码高亮渲染 ③ 会话多轮串接。

一、L1 基础设施:怎么起底盘

1.1 推理服务有

我方实现:本地 ollama(端口 11434),模型归档在 D:\ollama_models(OLLAMA_MODELS 环境变量)。不走外脑 API,自己机器上跑——好处:数据不出门、零调用费、断网可用。

给 K3 的话:起步可先接外脑 API(快),但记住这条路是「租脑子」;攒够语料就走我方这条——本地 ollama / vLLM 自部署,模型归自己。

1.2 服务编排(三个常驻服务 + 一个库)有
端口服务入口作用
80静态页服务_serve_web.py全站 HTML,反代 /api → 8979
8979药材谷后端后端路由/main.py交易/采集/蜂群等 916 个端点
8981本草大脑底座本草大脑_v149/backend/main.py大模型对话 + 166 引擎,144 端点
3307MariaDB_数据库/mariadb_data会话/消息/用户/配额落库

二、L2 模型层 + L3 微调层:脑子哪来、怎么练

2.1 在册模型(实扫 6 个)有
模型干什么我方用法
yaocai-q4-v5药材谷专用(第 5 版微调)对话台默认「Yaocaigu-4B」
qwen2.5:7b通用对话兜底 / 角色扮演
qwen2.5vl:7b视觉理解真读图——拍照识药
bge-m3向量化语义检索(管道待接)

注意:另有 2 个模型属别的项目,我方页面用白名单 屏蔽过滤,不混用。

3.1 微调工程(train/ 全套)超配

真实文件:train/ 下有 lora_train.py(LoRA SFT)· dpo_train.py(偏好对齐)· prepare_sft.py(语料制备)· merge_lora.py(合权重)· evaluate.py(评测)· 数据配方.md。

产出:yaocai-q4-v5 已经练出来并入 ollama。自训服务器:药材谷自己的香港服务器 43.161.221.92(不是别家的机器),训练管线待部署。

K3 可直接抄:这一层就是「合脑子」的车间——素材(prepare)→ SFT(lora)→ 对齐(dpo)→ 合并(merge)→ 评测(evaluate)五步,缺一不可。

三、L4 数据层 + L5 检索层:知识从哪来、怎么找

4.1 数据家底有

种子种苗档案:后端路由/data/seedling.json 等 4 表(含意向单、跳单防控)。

知识图谱本体:本草大脑_v149/backend/kg/ontology_loader.py——五层记忆的语义层会往这里沉淀三元组(见第五节)。

采集蜂数据:后端路由/data/swarm_*.json 共 20 个(行情/资讯/审核/集群…)。

护栏库:backend/guard/(违禁词 / 敏感词 / 内容护栏 / 记忆护栏)——输入输出都要过安检。

5.1 检索:我方走「规则引擎」这条路部分

我方特色:166 个 bre/*.py——把中医药知识写成确定性规则引擎(配伍禁忌 / 道地 / 炮制 / 采收 / 煎药…)。查得到的可解释、可复现、不会瞎编;这是向量检索给不了的确定性。

已暴露检索端点:GET /api/v1/herbs/search · /api/v1/prescriptions/search(关键词检索)。

缺口(如实说):向量检索管道未接——bge-m3 模型已在册,但「切块 → 向量化 → pgvector → 检索 top5 → 门槛拒答」这条链还没串。这正是 K3 药方二要补的 minScore 0.72 那段。

给 K3 的话:你那边规则 + 向量两条腿都要:规则管「确定的硬知识」(禁忌/剂量),向量管「软资料」(药典全文/行情资讯)。只靠向量会飘,只靠规则不够广。

四、L6 工具层:引擎从「只能看」到「真能查」

6.1 引擎名册(真实数字)超配

名册:plugins/agents/manifest.json → version gen-164 · 165 台 · 已接线 164 · 孤儿 0(生成物,跑 tools/rebuild_manifest.py 重生)。

三个通用端点(照抄即可):

GET /api/v1/bre/{engine}/demo              # 无参演示
GET /api/v1/bre/{engine}/ask?herb=附子      # 带参真查(#276 新增)
GET /api/v1/bre/federate?herb=附子          # 联邦:19 台并行(#277)

要点:ask 用 inspect 嗅探函数首参名自动传参;federate 扫名册自动发现「接受药材入参」的引擎并行执行——新引擎上线自动入列,不用改代码。这比一个个写 function calling 省事得多。

五、L9 会话 / 记忆层 ★(你点名的重点一:记忆怎么存)

9.1 会话(多轮 + 落库)有

真实实现:routers/chat.py —— 每轮把 user/assistant 消息写 Session_ / Message 两张表;/api/v1/chat/history 列最近 50 个会话、/{sid}/messages 取回某会话全部消息(这就是「跨会话历史」的真身)。

缺口(如实说):主前端 index.html 发送时 session_id:null → 每次是全新会话,暂未把上一轮历史喂回。后端能力已就绪,前端续聊待接。

9.2 五层记忆 ★ 我方自研超配

真实文件:backend/plugins/memory_layers.py —— FiveLayerMemory(v154·v31 图纸):

层装什么机制
① 工作记忆 Working当前任务dict 键值
② 短期记忆 Short最近对话滑窗 window=10,超窗 pop(0) → 挤进长期摘要
③ 情景记忆 Episodic事件 / 成交mark_episode(title,data)
④ 长期记忆 Long用户画像 + 摘要learn(k,v);老对话压成 summaries
⑤ 语义记忆 Semantic实体→事实absorb(实体,事实),联动知识图谱本体沉淀三元组
# 出 prompt 前取上下文(真代码)
m.context() → {working, recent=short[-5:], episodes=episodic[-3:],
               profile=long, knowledge=semantic[:5]}

给 K3 的话:你的「短期滑窗 6 轮 + 长期画像表」是对的,但可以再拆细——添上「情景记忆(干过哪些事)」和「语义记忆(沉淀成图谱)」两层,系统才会越用越像老中医,而不只是记住你叫啥。

9.3 守夜人(离线巩固 · 系统的「睡眠」)★超配

真实文件:backend/bre/nightly_consolidation.py —— Consolidator.sleep():白天的日间轨迹 → 压缩短记忆 → 蒸馏实体(absorb 进语义层)→ 去重 → 写明日就绪报告。

每日进化编排:backend/plugins/daily_loop.py —— 一键夜巡四步:好奇心(白天缺口) → 守夜人(睡眠巩固) → 梦境(反事实推演) → 进化闭环(明日任务),服务器 crontab 02:00 跑。

# daily_loop 夜巡(真代码节选)
step1 = 好奇心()                    # 找白天没答上的缺口
step2 = 守夜人.sleep(日间轨迹, 记忆)  # 压缩+蒸馏+去重
step3 = 梦境.dream(决策)             # 反事实推演
step4 = 进化()                      # 明日按清单执行

给 K3 的话:记忆不是存了就行,要「睡一觉」才会长脑子——白天积累,夜里压缩蒸馏去重。这条是很多底座忽略的,抄走。

9.4 AGI 记忆台账(前端可视化四台)有

我方另有四张浏览器本地台账(localStorage),把记忆治理做成了可视页面:

页键作用
AGI 记忆巩固台yc_agi_memory新经验→向量比对→新增/合并/冲突
AGI 记忆闭环台yc_agi_loop增量幂等沉淀 + 自动轮询回写
AGI 评审团能力看板yc_agi_tracks轨迹 / 工具成功 / 评审一致率度量
AGI 冲突预裁台yc_agi_governance六规则冲突预裁 + 人工留口

六、L7 Agent 编排:怎么「想」和「派活」 ★(你点名的重点二:调度)

7.1 意图路由(决定派谁)有

真实文件:backend/agents.py → route_intent(query, has_image, skills) —— 用关键词/规则把问题分派给对应引擎:

# 真代码节选:问题 → 派哪些引擎
图片 或 skills含identify  → ["herb_identify"]        # 识药
方/剂量/禁忌/配伍/反/畏    → ["prescription_audit","herb_info"]  # 审方
《/古籍/原文/古人          → ["classics"]             # 古籍
价格/行情/涨/产地          → ["market","herb_info"]   # 行情
写/PPT/方案/合同/文案      → ["writer"]               # 代写
种植N亩/投资成本           → ["calculator"]           # 测算
兜底                       → ["herb_info"]

更高级的决策:plugins/decision_router.py —— DecisionRouter:配了 vLLM 地址就用小模型输出结构化决策 {choice,score,prob};没配就规则兜底(零依赖)。LLM 决策 + 规则兜底双模。

另有:plugins/leader.py identify() 意图路由 + plugins/agents/driver.py 按 manifest 取 engine 并 __import__ 调用(派单执行)。

7.2 并行编排(怎么跑得快)★有
# agents.py swarm() 真代码节选——多引擎并行
plan = route_intent(query, has_image, skills)
if 并行(默认开) and len(plan) > 1:
    tasks = [协程(识药) if 识药 else 线程池(引擎) for 引擎 in plan]
    results = await asyncio.gather(*tasks)     # ← 真并行,不是排队
else:
    results = [串行执行每个引擎]
content = safety_review(results, plan)         # 汇总后过安全复核
return {content, sources, agents=plan}

要点:多个引擎用 asyncio.gather + 线程池真并行(识药是协程、其余同步引擎丢线程池),不是一个个等。K3 的 ReAct 循环(转 3 圈封顶)是串行工具调用;我方这套是「一次派多个、并行收结果」——两条路各有场景:追问式多轮用 ReAct,一次要多源汇总用并行。

7.3 蜂群调度中枢(自动派单闭环)★超配

真实文件:后端路由/routes/swarm_orchestrator.py —— 定位是「架在底座之上的编排层」,把 任务入队 → 自动派单(按职能匹配蜂群) → 工位执行 → 心跳巡检 → 失败重试 → 熔断 串成自动闭环。

# 派单规则(真代码节选)
RULES = {
 "collect": {组:"采集蜂", 执行器:"swarm_collect", human_gate:False},
 "content": {组:"内容蜂", 执行器:"swarm_content", human_gate:False},
 ...
}
# 铁律①:human_gate=True 的职能(发布/资金)自动派单只到「待人工确认」,绝不自动执行

18 个蜂群模块(在 后端路由/routes/):采集/内容/情报/审核/营销/集群/流水线/名册/技能/资金闸门/治理…

给 K3 的话:「分群怎么调度」的答案是——先按职能分群(采集蜂/内容蜂/情报蜂…),再来一个中枢按任务职能自动派单,超权限的(对外发布、花钱)必须留人工闸门。别让 Agent 手里没缰绳。

7.4 定时任务调度(cron 那套)有

我方两处定时:① 夜巡(daily_loop,crontab 02:00,见 9.3);② 后端 后台守护线程(security.py / seed_data.py / routers/bre.py 等 6 个模块用 threading 起常驻线程)。

# 与 K3 的 cron 写法对应(我方同构、真实在跑)
cron.schedule('* * * * *', async ()=>{
  待办 = 查任务表(下次运行 < 现在)
  for 任务 of 待办: 结果 = 执行(); SSE推(用户, 结果); 更新下次运行时间
})

K3 可直接抄:任务表 + 每分钟扫描 + 到点执行 + SSE 推 + 自动算下次时间——正是你文件里那段,逻辑等价。

七、L8 输出网关 + L10 前端:输出怎么快、怎么不卡 ★(你点名的重点三:流式)

7.1 我方两条流式路线(都真跑通)

路线 A · 底座 SSE(8981 真代码)

文件 backend/routers/chat.py。先算完,再按 24 字分块推。

async def gen():
  yield f"data: {{'session_id':sid,'agents':[...]}}\n\n"
  for i in range(0, len(content), 24):
    yield f"data: {{'delta': content[i:i+24]}}\n\n"
  yield f"data: {{'sources':[...],'done':True}}\n\n"

return StreamingResponse(gen(),
  media_type="text/event-stream")

前端 index.html:getReader() → 按 \n\n 切块 → 解析 data: → 把 d.delta 追加 DOM;d.agents 显示蜂群路由链。

路线 B · 本地大模型真 token 流

文件 药材谷_本地大模型对话台。模型出一个 token 推一个(TTFT 最低)。

// 对话台真代码
fetch(base()+'/api/chat', {method:'POST',
  body: JSON.stringify({model, messages, stream:true,
    options:{temperature:0.2, top_p:0.8}})})
// ollama 回 NDJSON,逐行解析:
if(j.message && j.message.content) onToken(j.message.content)
if(j.done) final = j

前端 getReader() + TextDecoder + {stream:true} → 打字机效果。

两者差别(一定要跟 K3 讲清):路线 B 是真流式(生成中就在推,首字最快);路线 A 是模拟流式(内容先算完再分块推,好处是推出去之前已过 safety_review 安全复核,代价是首字不省)。要极致流畅走 B,要内容先审后发走 A——我方两条都有,按场景选。

7.2 SSE 三件套(缺一不可 · 两边都适用)

Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
# 每条事件格式: data: {json}\n\n  ← 双换行分隔,前端按 \n\n 切块

7.3 前端渲染:不卡的要点

10.1 三线框 + 流式渲染有

主前端文件:本草大脑_v149/frontend/index.html(左抽屉 11 项 / 中间 hero+chips → 对话流 / 底部输入框)。

输入框:textarea(问药材、方剂、鉴别、行情…)+ 「+上传照片」+ 模型标识 Yaocaigu-4B · 进阶 + 发送「↑」+ 快捷 chips(药材鉴别/方药解析/煎法推荐/行情速览/配伍禁忌)。回车发送、按钮置灰防重复提交。

输出框:#msgs 消息流(用户气泡右 / 助手气泡左),助手气泡顶部实时显示「蜂群路由中… → herb_info → market · 已作答」。

K3 可照抄的防卡五机关(对应你文件 8.2):① rAF 批量刷 DOM(别每个 token 都 setState)② 句子级渲染(攒够一句再刷)③ AbortController 停止键④ 流式 Markdown 安全渲染 ⑤ 发送防抖。我方侧重 ①②⑤,③④(停止键 / Markdown 渲染)是待补项。

10.2 我方真缺口(如实列)待补

① Markdown / 代码高亮渲染:当前输出是纯文本 textContent 追加,未做 Markdown 流式渲染;② 引用角标:sources 已随流返回,前端未渲染角标;③ 停止键:未接 AbortController。

这三项正是 K3 图纸里比我们细的地方,照抄回去补上即可。

八、完整一趟流程(真链路:从输入到渲染)

用户输入"当归今天什么价"
 ① 前端 index.html:send() → 存 user 消息 → POST /api/v1/chat/completions
    (session_id:null → 后端新建会话)
 ② 网关 8981:check_and_consume_quota 配额 → 存 Session_/Message 落库
 ③ 编排 agents.swarm():route_intent("价格/行情" → ["market","herb_info"])
 ④ 并行:market + herb_info 两个引擎 asyncio.gather 同时跑
 ⑤ 汇总 safety_review() 过安全复核 → 得 {content, sources, agents}
 ⑥ 网关 SSE:先推 {agents} → 按 24 字推 {delta} → 推 {sources, done}
 ⑦ 前端 getReader → 按 \n\n 切块 → d.delta 追加 DOM → 「已作答」
 = 内容先审后发、多引擎并行、前端边收边显
与 K3 的对照:你的链路多了「RAG 检索 + 图文 + 引用角标」,我方链路强在「规则引擎并行 + 安全复核 + 蜂群路由链」。合起来才是最全的——你的 RAG 门槛(minScore 0.72)+ 我方的并行编排与守夜人记忆,两边互相补。

九、给 K3 的验收口诀(照我方真实提炼)

维度口诀我方真实对应
输入带画像、带资料五层记忆 context() 注入 + 检索资料拼 prompt
调度先分群、再派单、超权限留闸门蜂群调度中枢 RULES + human_gate 铁律
输出一块一推、一帧一刷SSE 分块 / 真 token 流 + getReader + rAF
记忆短期滑窗、长期入库、夜里睡一觉五层记忆 + 守夜人 + 每日进化编排
不知道拒答不瞎编规则引擎确定性 + RAG 门槛(待接)+ 安全复核
诚实边界(我方自查,不吹): ① 向量检索管道未接——bge-m3 在册但「切块→向量化→pgvector→门槛拒答」未串通,这是真缺口; ② 底座 SSE 是模拟流式(先算完再分块),真 token 流在本地对话台那条; ③ 主前端会话续聊未接(session_id 传 null),后端 Session_/Message 表已就绪但前端未回喂历史; ④ 前端Markdown/高亮/角标/停止键四项待补; ⑤ 十层中「166 引擎 / 五层记忆 / 守夜人 / 蜂群中枢 / 微调工程」为我方超配项(K3 图纸未含),非行业标配,属自研增量; ⑥ 本页所有结论均来自脚本实扫(_scan279_layers.json 59 条证据)与真文件通读,未含推测。
药材谷 · 本草大脑底座 · 十层详解(给 K3)|实扫取证 · 持续推进 · 持续达成 | ← 回总门户