Files
group_xinghuo_jinrong/docs/course/jinrong-module-customer/modules/01-capabilities.html
T

108 lines
6.8 KiB
HTML
Raw Normal View History

<section class="module" id="module-1">
<div class="module-inner">
<p class="eyebrow animate-in">模块 1 · 客户视角</p>
<h1 class="module-title animate-in">客户能做什么?<br>从 SSE 对话到 Core 只读</h1>
<p class="module-lead animate-in">
登录客户(如 <code>CUST-9527</code>)打开「客户助手」后,可走<strong>同步</strong>或
<span class="term" data-definition="SSE = Server-Sent Events,服务器像打字一样一段段把回复推给浏览器,不用等整段话生成完。">SSE 流式</span>
对话。未登录访客另有<strong>游客试聊</strong>(只 RAG、不查持仓)。
2026-09 <code>merger</code> 分支:客户线 SSE 已接通,测试基线 **786 passed**。
</p>
<div class="screen animate-in">
<h2>四条能力线(指挥 AI 改功能前先对齐)</h2>
<div class="pattern-cards">
<div class="pattern-card">
<h3>对话 SSE / 同步</h3>
<p><code>POST /api/chat/stream</code> 或 <code>POST /api/chat</code>,请求头 <code>X-Agent-Type: customer</code> + Bearer JWT。</p>
</div>
<div class="pattern-card">
<h3>持仓 / 流水 / 风评 / 净值</h3>
<p>意图命中后走 Core 模拟库只读查询 Tool(<code>core_ro_tool.py</code>);含 C-05 最新净值(非实时);C-04 查持仓时可 inline 阈值提醒。</p>
</div>
<div class="pattern-card">
<h3>产品规则 RAG</h3>
<p><code>fin_*</code> 知识库(Milvus)回答申购赎回、费率等产品咨询;画像语境注入但不泄露敏感字段。</p>
</div>
<div class="pattern-card">
<h3>游客试聊</h3>
<p><code>POST /api/chat/visitor</code> 免登录,游客试聊 9 节点编排(<code>visitor_service.py</code>),不写客户会话表。</p>
</div>
</div>
<div class="callout callout-accent">
<strong>和理财师线的区别:</strong> 客户线走登录客户 14 节点 LangGraph 编排(<code>customer_service.py</code>),<strong>不走</strong> 顾问通用 tool→llm→guard 编排(<code>agent_service.py</code>)。
</div>
</div>
<div class="screen animate-in">
<h2>数据流:浏览器问「我持仓多少」</h2>
<p>客户发消息后,四 Agent 对话 HTTP 入口(<code>chat.py</code>)按 <code>X-Agent-Type</code> 分流到客户编排,再查 Core。</p>
<div class="flow-animation" data-steps='[
{"highlight":"flow-actor-1","label":"浏览器:ChatPanel 带 JWT + X-Agent-Type: customer"},
{"highlight":"flow-actor-2","label":"四 Agent 对话 HTTP 入口(chat.py):鉴权、建 session、分流 customer 分支","packet":true,"from":"1","to":"2"},
{"highlight":"flow-actor-3","label":"customer_service:意图→tool_call→interpret(数值来自 Core)","packet":true,"from":"2","to":"3"},
{"highlight":"flow-actor-4","label":"Core 只读查询 Tool(core_ro_tool.py):SQL 只读 + fact_text 脱敏模板","packet":true,"from":"3","to":"4"},
{"highlight":"flow-actor-1","label":"SSE 分块推送完整回复 + MySQL 落会话","packet":true,"from":"4","to":"1"}
]'>
<div class="flow-actors">
<div class="flow-actor" id="flow-actor-1"><span class="flow-actor-icon">🖥</span><span>浏览器</span></div>
<div class="flow-actor" id="flow-actor-2"><span class="flow-actor-icon">🚪</span><span>对话 HTTP 入口(chat.py)</span></div>
<div class="flow-actor" id="flow-actor-3"><span class="flow-actor-icon">🤖</span><span>customer_service</span></div>
<div class="flow-actor" id="flow-actor-4"><span class="flow-actor-icon">🗄</span><span>core_ro_tool</span></div>
</div>
<p class="flow-step-label">点击「下一步」看请求怎么走</p>
<div class="flow-controls">
<button class="btn flow-next-btn">下一步</button>
<button class="btn flow-reset-btn">重来</button>
</div>
</div>
</div>
<div class="screen animate-in">
<div class="translation-block">
<div class="translation-code">
<span class="translation-label">入口 · 四 Agent 对话 HTTP 入口(chat.py)</span>
<pre><code><span class="code-line"><span class="code-keyword">if</span> agent_type == <span class="code-string">"customer"</span>:</span>
<span class="code-line"> host_ctx = host_auth_for_customer_service(auth, trace_id=trace_id)</span>
<span class="code-line"> customer_prep = prepare_customer_stream(</span>
<span class="code-line"> host_ctx, message, sid, cust_id, req.end_session</span>
<span class="code-line"> )</span>
<span class="code-line"> <span class="code-comment"># 图跑完后按 chunks 推 SSE</span></span></code></pre>
</div>
<div class="translation-english">
<span class="translation-label">白话</span>
<div class="translation-lines">
<p class="tl">看到 customer 就换轨道:不进 agent_service,改走客户专用编排。</p>
<p class="tl">先把 JWT 转成 customer_service 认识的 AuthContext(字段名对齐)。</p>
<p class="tl">流式路径:LangGraph 整图跑完,再把回复切成块推给前端——Tool/RAG 仍是同步完成。</p>
</div>
</div>
</div>
<div class="quiz-container" id="quiz-customer-m1">
<div class="quiz-question-block"
data-correct="option-b"
data-explanation-right="对。游客走 /api/chat/visitor + visitor_service,免 JWT,不查持仓/流水。"
data-explanation-wrong="游客试聊和登录客户是两条线:无 JWT、无 Core 客户数据查询。">
<h3 class="quiz-question">未登录访客在首页试聊,会查到自己的持仓吗?</h3>
<div class="quiz-options">
<button class="quiz-option" data-value="option-a" onclick="selectOption(this)">
<div class="quiz-option-radio"></div><span>会,走同一套 customer_service</span>
</button>
<button class="quiz-option" data-value="option-b" onclick="selectOption(this)">
<div class="quiz-option-radio"></div><span>不会,只 RAG + 闲聊,无客户数据</span>
</button>
<button class="quiz-option" data-value="option-c" onclick="selectOption(this)">
<div class="quiz-option-radio"></div><span>会,但要填客户号</span>
</button>
</div>
<div class="quiz-feedback"></div>
</div>
<button class="quiz-check-btn" onclick="checkQuiz('quiz-customer-m1')">检查答案</button>
<button class="quiz-reset-btn" onclick="resetQuiz('quiz-customer-m1')">重做</button>
</div>
</div>
</div>
</section>