Skip to content

LLM 输出路径

字数
2202 字
阅读时间
9 分钟

本页标出普通聊天与接话的代码入口,方便改接线。用户向说明见 LLM 对话与复读

普通 @ 聊天走 Bot Provider,在 Bot 进程内完成;不要为这条路径增加 Pallas-Bot-AI / :9099 / HTTP callback。媒体与遗留 RWKV 另见 Agent 生命周期 与运维文档。

出口总闸

所有 LLM 出口(complete_chat_messagefetch_embeddings_sync)统一受 pallas.product.llm.availability.llm_calls_enabled 约束:LLM_CHAT_ENABLED 为关,或 llm_chat 插件被全实例禁用时,直接不发请求。消息入口另有 llm_plugin_disabled_for_scope 做按牛/按群拦截;后台循环、work/embed 辅进程在各自任务入口自查同一作用域,避免绕过插件禁用。治理细节见 插件治理

两条出口

text
群消息
 ├─ 统一 ingress 怒气门控 → 记录时间线;静默时停止后续副作用
 │  └─ @ / to_me → packages/llm_chat/chat_message.py
 │     persona +【表达参考】→ client.submit_chat_task

 └─ 非 @ 接话 → packages/repeater/handlers/message.py
       → 原始候选检索、人格加权、过滤与去重
       → Repeater 直接投递原语料

普通聊天在 Bot 进程内执行:submit_chat_task 安排 kernel_runner。通常由后者调用 Provider、运行工具循环,并通过 pallas/product/llm/delivery.pydeliver_llm_chat_result 交给既有投递入口;若 semantic style 给出通过相关性与近期回复去重的 direct_candidate,并通过滚动窗口 15% 配额,kernel 会直接投递该真实语料而不调用 Provider。该判断不对语料内容作额外价值判断。Repeater 日常接话自身不创建 LLM 任务。

工具循环会在模型提出 tool call 后执行工具、将结果追加回上下文并继续补全。默认工具集会按场景选择;延迟公开的工具可由 tools.find 发现,并在后续轮次加入可调用集合。查询工具有单轮调用预算、重复参数去重和最终回答阶段;副作用工具成功后才允许静默。延迟完成的外部工具只派发任务;任务结果由其自身通道回传,不阻塞当前 LLM 回复。

显式查询超过 3 秒且已经开始实际工具调用时,kernel 最多发送一次“我查一下。”进度气泡;该气泡不写入会话历史、表达学习或最终答案上下文。

LLM 输出管线

LLM 输出管线与表达数据粒度

@ 对话在 Bot 进程内完成:Provider 返回文本后,从生成到发进群依次经过:

步骤位置说明
表达语料直投kernel_runner.py表达库 direct_candidate 通过去重与配额时直接投递真实语料,跳过 Provider
生成 + 工具循环complete_with_tool_loop模型提 tool call → 执行工具 → 结果回填上下文继续补全
人设输出防火墙pallas/product/llm/persona_output_firewall.py命中规则可带修正指令重试,或回落 fallback
JSON 契约解析structured_reply.py parse_structured_reply期望 reply_segments 数组逐条成气泡;纯文本退化单段
输出过滤output_filter.py语料污染词、续写残片、角色 / 形态守卫、长度硬闸(由 reply_shape 的 p50 段长推导 reply_max_length,超限找干净断点压短,否则回落 fallback)
短气泡兜底拆分reply_postprocess.py split_short_reply_segmentsshort 取向但只有单段时,按句末标点 / 换行拆成多气泡
轻量后处理apply_reply_postprocess错别字、句尾句号
多气泡投递delivery.py deliver_llm_callback_success逐条发送,返回 DeliveryOutcomesent / partial / failed / silent 由真实发送回执推导,气泡间按上句长度叠加随机抖动(0.5~3.5s)
学习回写会话 / behavior_store / repeater_feedback / auto_episode投递成功后写历史、行为与表达

LLM turn telemetry

LLM turn telemetry 从消息进入 llm_chat handler 后开始,以随机 turn_id 关联 ingress、speak perception、reply gate、necessity、submit、Provider、output 和 delivery 各阶段。首期不覆盖完全未匹配 llm_chat rule 的入站消息,也不改变任何门控、生成或投递决策。

事件写入独立的 data/pb_webui/llm_telemetry/ JSONL 文件,并由按日 report 聚合。事件只保留固定 allowlist、文本形态与长度分桶,以及运行时 HMAC hash;不写入用户消息、Bot 回复、prompt、异常正文或原始 Bot/群/用户/消息 ID。turn_id 会随异步 TaskManager metadata 贯穿到 Provider 和 callback delivery。

Telemetry 是 best-effort 的旁路观测:写 key、序列化、目录或文件失败时只记录限频运维日志,不阻断聊天。完整 prompt 和消息内容仍属于独立的 runtime snapshot/trace 调试路径,不能把两类数据混为同一份报告。

表达数据粒度

数据存储粒度影响
表达风格锚点 / 例句repeater_semantic_style.pyprofiles.json每 bot × 每群 独立(key bot_id:group_id:scene注入「群表达指导」block;重置命令只清本 bot 本群
回复画像(气泡数 / 节奏 / 长度)group config style_profilegroup_profiler.py群维度共享决定 reply_shape 的段数、节奏与长度取向;其 p50 段长再参与推导 reply_max_length 硬上限

同群不同 bot 的表达指导互不共享;回复画像是群统计,同群所有 bot 共用。WebUI 管理入口见 packages/pb_webui/llm_product_api.py

Prompt 组装

at-chat 系统提示词 pallas/product/persona/at_chat_system_prompt.txt 只承载背景 / 输出边界 / 群聊边界等不变原则,不再内嵌具体对话示范;接话的差异化由语义风格按 bot × 群 注入(见上表「群表达指导」「真人接话参考」)。ChatPromptAssemblerpallas/product/llm/assembler/chat_prompt.py)按变化频率从低到高依次组装:persona 核心 → 群表达指导 / 真人接话参考(随 profile 有数据才注入)→ 近期上下文(检索块 → 群时间线)→ reply_shape(回复形状与输出契约)→ turn policy → 当前时间 → 工具上下文,使支持前缀缓存的 Provider 可命中更长的稳定前缀。

任务路由与模型选择

所有 LLM 任务经 resolve_endpoint_candidates_for_task(task)pallas/product/llm/providers_store.py)取提供方候选:

text
routing.tasks[task]                       → 主提供方(WebUI 任务编排写入)
routing.task_backups[task]                → 全任务备用(可含 backup model)
routing.tier_backups[high|low]            → 档位备用(low 含记忆与后台任务)
routing.chain_fallback                    → 其余提供方兜底
provider.task_models[task] / default_model → 该提供方下的具体模型

任务分两类:

类别任务说明
highllm_chatdrunkWebUI「高级任务」主备
lowaffect_refineturn_decisionmemory_episodememory_person_factsmemory_ip_knowledgememory_graph_extractmemory_graph_hiergraphmemory_session_summarymemory_tool_summaryllm.relationship.affinityrepeater.semantic_styleWebUI「低级任务」主备
独立sticker_vision「全任务」视图单独指定;无配置时回落到提供方 default_model

后台与记忆任务调用频次远高于对话且无需强模型,因此并入低档:在 WebUI 改一次低档主备即可全部生效;没有独立配置时仍回落到提供方 default_model

关键锚点

步骤位置
Repeater 候选与投递packages/repeater/responder.pypackages/repeater/handlers/message.py
LLM 群级表达指导pallas/product/llm/repeater_semantic_style.py(注入消费);pallas/product/llm/group_insight_processor.py(从 message 表重建成对样本,批量标注落盘)
表达库存取 / 学习pallas/product/persona/expression_*.py
进程内投递pallas/product/llm/delivery.pydeliver_llm_chat_result);kernel_runner.py 调用 delivery
媒体 / HTTP callback 壳pallas/core/platform/ai_callback/runner.py(薄壳,复用 delivery)
配置键pallas/product/llm/config.py;WebUI 段见 env_sections.py(侧栏 AI 配置

群洞察的调度、8 个候选对的批量含义、持久化游标、预算和记忆层批量边界见群洞察与语义风格指导器

约束

  • 怒气门控发生在 direct runtime 与 matcher 之前。静默不是丢弃入站消息:消息仍持久化并带 suppressed_by_rage=true,但不会被视为 Bot 已回复,也不会进入 LLM、工具或 Repeater 处理。

  • 攻击增量由攻击词数量、短窗口连续攻击次数和当前怒气共同决定;75 分进入静默,低于 75 才恢复。静默期间不重复累积怒气、不重复扣好感、不延长截止时间。

  • 日常接话只使用 Repeater 语料,不调用 LLM 生成、选句、润色或拼接。

  • @、follow-up 与工具回合独立走 llm_chat

  • Repeater 学到的群级表达可以只读注入 llm_chat;其中有界 direct_candidate 仅替代本次 llm_chat Provider 补全,不反向控制 Repeater 候选与投递。

  • 在线链路不再存在 Repeater 的 select、polish 或 fallback LLM 任务。

  • 表达库当前是单群;跨群另开任务,不要默认同库检索。

后续阅读