e-pigeon 后端 · LLM 调用场景索引

分章浏览。完整说明见 首页

回合 need 消歧与 mes 类型

本章条目均为单独 LLM 请求;提示词并入主对话 system_final 拼接常量。

多条 need 时 LLM 选相关 need_id

app/chat_turn_mes.py · _llm_pick_need_if_ambiguous;app/chat_labeling_flow.py 亦有 pick_relevant_need_id_for_message

user 块内拼对话与需求列表,工具 pick_relevant_need_for_message(实现见 llm_client)。

展开:system + user 块结构 · 修改备忘

systemLLMClient.pick_relevant_need_id_for_message):

你只负责调用工具 pick_relevant_need_for_message,不要输出自然语言。
须严格从用户文中的【允许的 need_id 列表】中选一条;不得编造列表外的 id。
用户明确讨论某条需求主题时,优先按 needs_desc 与近期带 need_id 的消息对齐该条。
若无法判断或与任一条均无关,need_id 填 -1。

userchat_turn_mes._build_need_disambiguation_user_block 拼装,数据库查询结果代入):

【本轮用户消息】
…

【允许的 need_id 全集】(工具 need_id 只能填其中一条,或填 -1)
…

【被征询方视角:仍活跃的候选 need(need_id|候选人 status|需求摘要)】
- need_id=…,status=…:…
(无)

【提出方视角:collecting 的 need(need_id|需求摘要)】
- need_id=…:…
(无)

【最近约 20 条本会话消息(含已标注 need_id,用于对齐话题)】
[need_id=…][mes_type][user|assistant] …

【输出】必须调用工具 pick_relevant_need_for_message。

classify_turn_mes_type

app/chat_turn_mes.py · apply_chat_turn_mes_labels

回合结束后为用户消息标注 mes_type(对话/诉求方需求/被征询/传话等)。system 见 LLMClient.classify_turn_mes_type

展开:system + user(含分类规则全文)· 修改备忘

systemLLMClient.classify_turn_mes_type):

你只负责调用工具 classify_turn_mes_type,不要输出自然语言。
仔细阅读用户消息中的【分类规则】与【上下文】,只输出四类 mes_type 之一。
同一件事连贯承接时不要判「对话」;须遵守用户文中的【同一件事·连续一致】与【谨慎原则·边界从严】。
对 user_needs 链路:未确定诉求方已明确指使/结案、或被询问方已明确回复时,延续对应类型而非改判「对话」。

user 以「分类规则」长文起头,后接本轮消息、飞鸽回复、进度提示、need 列表与摘录(_build_classify_turn_mes_type_user_block)。规则正文如下(与源码一致):

【分类规则】请只依据对话语义在下列四类中选一类(不要输出 need_id,系统会另算)。
本规则优先约束:**由 user_needs(找人/匹配/征询意愿等)触发的飞鸽对话**;传话、纯闲聊另当别论。

【need_id 与 mes_type·硬性一致(系统也会强制校验)】
- 仅当本轮语义属于「诉求方消息」或「被询问方消息」时,本条用户消息与本轮飞鸽回复在库里会写入**非空**的 messages.need_id;「对话」「传话」时 need_id **必须为空**。
- 反之:一旦某条消息带有 need_id,其 mes_type **只能是**「诉求方消息」或「被询问方消息」二者之一。
- 判定「本条是否挂在某个 need_id」时,系统侧只参考:**当前用户**在 user_needs 中 collecting 的 needs_desc 列表、**当前用户**在 need_match_candidates 中仍活跃的候选所指向的 user_needs.needs_desc,以及下方【最近对话摘录】(约最近 20 条)里各条已标注的脉络;优先级为:
  1)是否与**该用户自己的** user_needs(提出方 collecting)中的某条需求语义相关 → 选用对应 need_id,mes_type 为「诉求方消息」;
  2)若上项不足以定夺,是否与 **need_match_candidates 所对应的那条** user_needs(你是候选人、候选仍活跃)语义相关 → 选用该 need_id,mes_type 为「被询问方消息」;
  3)若仍不足以定夺,是否与**上下文中某条已有 need_id 脉络的消息**仍在谈同一件事 → 延续该 need_id 与同侧 mes_type。
- 你在选「诉求方消息 / 被询问方消息」时,应默认系统会把 need_id 落在与上列优先级一致的候选上;不要随意选「对话」来规避带 need 的活跃征询链(除非已明确结案/拒绝且与需求无关)。

【谨慎原则·边界从严(极重要)】判定「这一段需求/询问对话是否已结束」时**宁可保守**:若不能**有把握**认定用户已给出**明确指使**(诉求方侧)或**明确回复**(被询问方侧),则**延续**当前链路对应的 mes_type,**不要**因飞鸽或用户某句看似「告一段落」就改判「对话」。
- 与产品一致:飞鸽在不确定时应倾向**再问一句澄清**,分类侧同理——**不确定 = 仍算同一段需求链或询问链**。
- 「明确指使」(诉求方):如清晰同意推进、指定下一步(去问谁、按哪套方案办)、明确结案(不需要了/先不搞了)等;含糊的「再看看」「嗯」「行吧」、未表态的附和、仍在补充条件或讨价还价,**不算**结案。
- 「明确回复」(被询问方):如清晰的愿意/不愿意/暂不参与、或对该次询问给出**可视为最终决定**的答复;单纯的「我想想」「不了解情况再问问」、追问背景、尚未表态,**不算**结束被询问方段。

【同 need 双向沟通】围绕**同一条** need、飞鸽在诉求方与被询问方之间中转的沟通(含转述、追问、补充、反馈),在**各自用户**的会话里仍分别标「诉求方消息」或「被询问方消息」并带该 need_id;**不要**因「是在帮对方转达」就改判「内容沟通」——「内容沟通」仅用于与当前 need 管线**无关**的日常 buddy 转告。

【同 need·收口句】飞鸽若先向用户点明本段性质为**反馈**、**补充**或**询问**,再归纳要点或准备同步对侧,只要仍属同一条 need 的中转沟通,本轮仍判「诉求方消息」或「被询问方消息」,勿因「像在总结」就判「对话」。

【同一件事·连续一致(重要)】本系统会把**本轮**用户消息与同轮飞鸽回复标成**同一个** mes_type。只要摘录里可见:当前轮与上文讲的是**同一件事**,或用户/飞鸽下一句是对上一句的**自然承接、补充、确认**且**没有明显话题转折**(未突然换成纯闲聊、无关问答),则**应**与上文已形成的链路保持一致:若整体是在走「提出方谈需求」链,本轮判「诉求方消息」;若整体是在走「被询问方表态」链,本轮判「被询问方消息」。**不要**在同一条需求/同一次询问的连贯来回里,把中间某轮判成「对话」——「对话」只用于**明确已脱离**需求链或询问链的独立闲聊。

【诉求方段·起止锚点】从飞鸽**向诉求方**发出与该条需求相关的实质性内容起(例如:说明进展、追问细节、呈现候选、请其选择或补充等;含系统进度提示类话术),到诉求方给出上文的**明确指使或明确结案**为止,其间**每一轮**(含飞鸽追问、用户犹豫或反问)**原则上均**标「诉求方消息」。飞鸽单句「好的/收到」若仍处在**同一需求未结案**的来回中,**不**视为转入「对话」。

【被询问方段·起止锚点】从飞鸽**向被询问方**发出与该 need 相关的征询或邀请起,到被询问方给出**明确回复**(见上)且上下文显示该次询问已收束为止,其间多轮(含用户反问、飞鸽解释背景)**原则上均**标「被询问方消息」。

【补充细节仍属诉求方】用户在补充时间、地点、人数、偏好等条件时,**未必**重复首轮的提出方式;只要语义上仍是对**同一条**找人/出行/帮忙类需求的延续,必须继续判「诉求方消息」,**不要**判「对话」。

1) 诉求方消息:用户处在「某条需求的提出方」一侧,与飞鸽讨论该需求相关的事(找人、匹配进展、补充条件、邀请候选人、询问结果等)。请结合上文与本轮判断,不要仅因库里存在 collecting 需求就判为此类。

【诉求方——口语启发(非硬规则)】用户话里出现「我想」「可不可以」「能不能」「帮我」「麻烦」「想请你」等**提出请求、求助、打听**的口吻时,**一般**倾向判为「诉求方消息」;**必须仍结合上文**确认是在谈「自己的需求/找人帮忙」而非无关闲聊。以「Hi」「哈喽」等寒暄开头**不改变**后续实质为提出需求的事实。「找搭子」「组队」「一起…去」「找人同行」「拼车」「约伴」等**找人、找链接**的表述,多属提出方发起的需求链,**不要**因语气轻松就判成「对话」。

【诉求方——连续段】从用户开始说清楚要帮什么忙(或飞鸽追问细节),直到诉求方**明确指使或结案**之前,这一连续段内的多轮来回**一般都**应判「诉求方消息」。若同一段里用户明确插入「顺便帮我传个话」「帮我问一下某某」等**日常转告 buddy** 语境,则该轮(或该插入所在语境)改判「内容沟通」。

2) 被询问方消息:用户处在「某条需求的被询问方/候选人」一侧,与飞鸽讨论是否愿意了解、表态、追问等。结合上文与本轮判断。

【被询问方——连续段】从飞鸽向用户**征询帮助意愿**(是否愿意了解、是否方便帮忙等),直到用户给出**明确回复**(或上下文已清晰收束)之前,整条链上的多轮来回**一般都**应判「被询问方消息」;**仍以语义为准、勿只看单句**,且与上文连贯时不要中途判「对话」。

3) 内容沟通:用户已在 buddy 传书关系下,请飞鸽向某位伙伴做**日常转告**(与需求匹配/候选人征询管线无关或明显熟人转告)。是否属转告链请根据对话**语义**判断,勿依赖系统提供的简单标签。

4) 对话:与上述均不符的**独立**闲聊、人设、无关问答;或话题已**明显切换**、与当前需求链/询问链**毫无关系**且**不可能**仍在同一条 need 流程内时再用此类。

【候选人 status(相对该 need)】pending=尚未表态;willing=愿意继续沟通;canceled=已拒绝或已结束参与;finished=该 need 下已结案归档。
在 status 为 **pending 或 willing** 期间,你与该用户关于该 need 的内容须判「诉求方消息」或「被询问方消息」并带对应 need_id,**勿**判「对话」;canceled/finished 后不再受此约束。

【说明】数据库与列表仅作参考;**最终类型由上下文语义决定**,但须遵守上条关于 pending/willing 的硬约束。

(其后 user 块继续拼接:【本轮用户消息】【本轮飞鸽主回复】、【本轮系统追加的进度提示】、【输出】工具行、【代码侧参考】、候选 need 列表、【最近对话摘录】——见源码。)

matches 后置:传话短句、relay 专用 mes 分类

app/routers/matches.py(chat 返回前/后处理)

classify_relay_short_ack_peer_or_wrapupclassify_relay_turn_mes_typeclassify_relay_assistant_promise_wrapup_other — 传话承诺/收尾等细粒度分类,均为 llm_client 内独立 system。

展开:classify_relay_* · system / user 骨架 · 修改备忘

classify_relay_short_ack_peer_or_wrapup

system:
你只负责调用工具 relay_short_ack_classify_intent,不要输出自然语言。结合【近期对话摘录】与【用户本条】在 relay_peer 与 wrapup_feige 间二选一;定义见工具 description。

user: 【近期对话摘录】… 【用户本条】… 【输出】必须调用工具…(失败兜底 JSON 见源码)

classify_relay_assistant_promise_wrapup_other

system:
你只负责调用工具 relay_assistant_classify_promise_wrapup_other,不要输出自然语言。严格按工具 description 在 feige_ack / promise / wrapup / other 四选一。

user: 【近期对话摘录】… 【用户本轮】… 【飞鸽本轮回复】… 【输出】…

classify_relay_turn_mes_type

system:
你只负责调用工具 classify_relay_turn_mes_type,不要输出自然语言。根据【近期对话摘录】【用户本轮】【飞鸽本轮回复】,在以下枚举中选一:请求传话 | 用户确认 | 内容沟通 | 对话;定义见工具 description。若用户要求转告的对象按语义尚非笔友、仅为匹配候选人等,应标「对话」而非「请求传话」。

user: 【近期对话摘录】… 【用户本轮】… 【飞鸽本轮回复】… 【输出】…