Files
group_xinghuo_jinrong/docs/course/jinrong-module-customer/modules/03-stream-rules.html
T
zhanghongyu_0626 4b8e11c9bd feat(threshold): Implement customer loss threshold configuration and notification system
- Added `ThresholdRepository` for managing customer loss threshold configurations and notifications.
- Introduced `threshold_service` to handle loss threshold alerts based on customer portfolio performance.
- Enhanced `customer_prompts` to include new intent for querying product net values.
- Updated `customer_service` to integrate new threshold alert functionality into existing workflows.
- Implemented `sanitize_postprocess` for improved compliance handling in customer interactions.
- Enhanced course documentation to reflect updates in advisor training modules and interactive elements.

This update significantly improves the customer experience by providing proactive loss threshold notifications and enhancing the overall service framework.
2026-09-10 10:57:40 +08:00

99 lines
6.6 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<section class="module" id="module-3">
<div class="module-inner">
<p class="eyebrow animate-in">模块 3 · 铁律与流式</p>
<h1 class="module-title animate-in">两条铁律 +<br>prepare_customer_stream</h1>
<p class="module-lead animate-in">
客户线能跑通,靠文件头写死的两条
<span class="term" data-definition="铁律 = 写进代码注释、测试会卡住的硬规则;违反会导致合规或数据错乱。">铁律</span>。
流式 SSE 看起来是「边生成边推」,实现上是<strong>先跑完整张 LangGraph,再切块推送</strong>。
</p>
<div class="screen animate-in">
<h2>铁律(指挥 AI 改代码时别碰)</h2>
<div class="pattern-cards">
<div class="pattern-card">
<h3>铁律 1 · 数值不经过 LLM 编造</h3>
<p>持仓、流水、风评等查询结果 100% 来自 Core 只读查询 Tool(<code>core_ro_tool.py</code>)的 <code>fact_text</code>。LLM 在 <code>interpret</code> / <code>generate</code> 里只做解读与组织语言,不能自己算数。</p>
</div>
<div class="pattern-card">
<h3>铁律 2 · customer_id 只来自 JWT</h3>
<p>四 Agent 对话 HTTP 入口(<code>chat.py</code>)在进图之前已从令牌解析客户号并做归属校验。图内 <code>state["customer_id"]</code> 不信用户消息里的「帮我查 CUST-xxx」。</p>
</div>
</div>
<div class="callout callout-warning">
<strong>和 advisor 线的差异:</strong> 理财师走顾问通用编排(<code>agent_service.py</code>)的 tool→llm→guard;客户走独立 14 节点图。别混用对话 Tool 编排(<code>tool_service.py</code>)关键词意图那套来改客户 RAG 分支。
</div>
</div>
<div class="screen animate-in">
<h2>流式真相:图跑完再切块</h2>
<p>方案 C 下 <code>prepare_customer_stream</code> 先调用 <code>run_customer_chat</code> 跑完整图,再用 <code>_chunk_reply_text</code> 切成 16 份左右推 SSE——Tool/RAG 仍是同步完成,不是 token 级流式。</p>
<div class="translation-block">
<div class="translation-code">
<span class="translation-label">CODE · prepare_customer_stream</span>
<pre><code><span class="code-line"><span class="code-keyword">def</span> prepare_customer_stream(</span>
<span class="code-line"> ctx, message, session_id, customer_id, end_session=<span class="code-keyword">False</span></span>
<span class="code-line">) -> dict[str, Any]:</span>
<span class="code-line"> reply, has_disclaimer, intent, transfer = run_customer_chat(</span>
<span class="code-line"> ctx, message, session_id, customer_id, end_session</span>
<span class="code-line"> )</span>
<span class="code-line"> <span class="code-keyword">return</span> {</span>
<span class="code-line"> <span class="code-string">"reply"</span>: reply,</span>
<span class="code-line"> <span class="code-string">"has_disclaimer"</span>: has_disclaimer,</span>
<span class="code-line"> <span class="code-string">"intent"</span>: intent,</span>
<span class="code-line"> <span class="code-string">"transfer_to_human"</span>: transfer,</span>
<span class="code-line"> <span class="code-string">"chunks"</span>: _chunk_reply_text(reply),</span>
<span class="code-line"> }</span></code></pre>
</div>
<div class="translation-english">
<span class="translation-label">白话</span>
<div class="translation-lines">
<p class="tl">入参里的 customer_id 是四 Agent 对话 HTTP 入口(<code>chat.py</code>)验完 JWT 后塞进来的,函数内部不再解析用户文本。</p>
<p class="tl">先拿到完整 reply(含 intent、是否转人工、是否附免责),再切片给 SSE 层逐块写。</p>
<p class="tl">改「真流式」要先动 LangGraph 执行模型,不是只改前端 ChatPanel。</p>
</div>
</div>
</div>
</div>
<div class="screen animate-in">
<h2>相关文件(改流式 / 铁律时打开这些)</h2>
<div class="file-tree animate-in">
<div class="tree-item tree-folder">app/service/</div>
<div class="tree-item tree-indent">登录客户 14 节点 LangGraph 编排(customer_service.py)— prepare_customer_stream</div>
<div class="tree-item tree-indent">游客试聊 9 节点 LangGraph 编排(visitor_service.py)— 无 Tool 查持仓</div>
<div class="tree-item tree-indent">RAG 检索层(rag_service.py)— fin_faq / fin_product / fin_policy</div>
<div class="tree-item tree-folder">app/api/</div>
<div class="tree-item tree-indent">四 Agent 对话 HTTP 入口(chat.py)— customer 分支分流 + SSE 写帧</div>
<div class="tree-item tree-indent">宿主 AuthContext → 模块 AuthContext 适配(auth_adapter.py)— host_auth_for_customer_service</div>
<div class="tree-item tree-folder">app/tool/</div>
<div class="tree-item tree-indent">客户 Agent Core 只读查询工具(core_ro_tool.py)— query_holdings / query_trades 等</div>
</div>
<div class="quiz-container" id="quiz-customer-m3">
<div class="quiz-question-block"
data-correct="option-c"
data-explanation-right="对。prepare_customer_stream 先 run_customer_chat 整图 invoke,再 _chunk_reply_text 切块;不是 LLM token 级流。"
data-explanation-wrong="客户 SSE 是「整图跑完再切块」,Tool/RAG 在推流前已同步完成。">
<h3 class="quiz-question">客户 SSE 流式回复,LangGraph 什么时候跑完?</h3>
<div class="quiz-options">
<button class="quiz-option" data-value="option-a" onclick="selectOption(this)">
<div class="quiz-option-radio"></div><span>每推一块就跑一个节点</span>
</button>
<button class="quiz-option" data-value="option-b" onclick="selectOption(this)">
<div class="quiz-option-radio"></div><span>只跑 interpret,前面跳过</span>
</button>
<button class="quiz-option" data-value="option-c" onclick="selectOption(this)">
<div class="quiz-option-radio"></div><span>推流前整图 invoke 完成</span>
</button>
</div>
<div class="quiz-feedback"></div>
</div>
<button class="quiz-check-btn" onclick="checkQuiz('quiz-customer-m3')">检查答案</button>
<button class="quiz-reset-btn" onclick="resetQuiz('quiz-customer-m3')">重做</button>
</div>
</div>
</div>
</section>