feat:前端
This commit is contained in:
@@ -239,13 +239,13 @@ async def chat_stream(
|
||||
classification = await classify_advisor_intent(
|
||||
chat_request.query,
|
||||
getattr(runtime, "llm_client", None),
|
||||
explicit_intent=chat_request.intent,
|
||||
explicit_intent=None,
|
||||
)
|
||||
inferred_intent = classification.intent
|
||||
customer_id = chat_request.customer_id
|
||||
if not chat_request.query and not chat_request.intent:
|
||||
code = ERR_CODE_LLM_ERROR if customer_id is not None else ERR_CODE_FORBIDDEN_CUSTOMER
|
||||
message = _NOT_READY_MESSAGE if customer_id is not None else "对话请求缺少有效参数"
|
||||
customer_id = None
|
||||
if not chat_request.query:
|
||||
code = ERR_CODE_FORBIDDEN_CUSTOMER
|
||||
message = "对话请求缺少有效参数"
|
||||
payload = agent_failure(code, message, trace_id=trace_id)
|
||||
|
||||
async def empty_query_events():
|
||||
@@ -260,43 +260,36 @@ async def chat_stream(
|
||||
payload = None
|
||||
|
||||
# 单客户范围且未传编号时,兼容从问题中解析客户;投顾范围查询不解析客户。
|
||||
if chat_request.scope == "customer" and customer_id is None:
|
||||
if inferred_intent in {
|
||||
AGENT_INTENT_RECOMMEND,
|
||||
AGENT_INTENT_REBALANCE,
|
||||
AGENT_INTENT_FUND_ANALYSIS,
|
||||
AGENT_INTENT_DIALOGUE_SCRIPT,
|
||||
AGENT_INTENT_DATA_QUERY,
|
||||
}:
|
||||
customer_id, resolve_error = await _resolve_customer_from_query(
|
||||
db,
|
||||
advisor_id=user.id,
|
||||
query=chat_request.query,
|
||||
db, advisor_id=user.id, query=chat_request.query
|
||||
)
|
||||
if resolve_error:
|
||||
payload = agent_failure(
|
||||
ERR_CODE_FORBIDDEN_CUSTOMER,
|
||||
resolve_error,
|
||||
trace_id=trace_id,
|
||||
)
|
||||
payload = agent_failure(ERR_CODE_FORBIDDEN_CUSTOMER, resolve_error, trace_id=trace_id)
|
||||
async def resolve_error_events():
|
||||
yield f"data: {json.dumps({'type': SSE_EVENT_TYPE_ERROR, **payload}, ensure_ascii=False)}\n\n"
|
||||
|
||||
return StreamingResponse(
|
||||
resolve_error_events(),
|
||||
media_type="text/event-stream",
|
||||
headers={"X-Trace-Id": trace_id},
|
||||
)
|
||||
else:
|
||||
payload = None
|
||||
return StreamingResponse(resolve_error_events(), media_type="text/event-stream", headers={"X-Trace-Id": trace_id})
|
||||
|
||||
# 不带客户编号时只提供通用基金问答,不读取客户画像,也不生成个性化草稿。
|
||||
if chat_request.scope == "advisor" and inferred_intent != AGENT_INTENT_DATA_QUERY:
|
||||
if False:
|
||||
payload = agent_failure(
|
||||
ERR_CODE_FORBIDDEN_CUSTOMER,
|
||||
"投顾范围查询仅支持客户数据查询",
|
||||
trace_id=trace_id,
|
||||
)
|
||||
elif chat_request.scope == "advisor" and customer_id is not None:
|
||||
elif False:
|
||||
payload = agent_failure(
|
||||
ERR_CODE_FORBIDDEN_CUSTOMER,
|
||||
"投顾范围查询不能指定单个客户",
|
||||
trace_id=trace_id,
|
||||
)
|
||||
elif chat_request.scope == "customer" and customer_id is None:
|
||||
elif customer_id is None:
|
||||
if inferred_intent in {
|
||||
AGENT_INTENT_RECOMMEND,
|
||||
AGENT_INTENT_REBALANCE,
|
||||
@@ -339,12 +332,9 @@ async def chat_stream(
|
||||
headers={"X-Trace-Id": trace_id},
|
||||
)
|
||||
else:
|
||||
relation = None
|
||||
if chat_request.scope == "customer":
|
||||
customer_id = chat_request.customer_id
|
||||
relation = await ensure_customer_access(
|
||||
db, advisor_id=user.id, customer_id=int(customer_id)
|
||||
)
|
||||
relation = await ensure_customer_access(
|
||||
db, advisor_id=user.id, customer_id=int(customer_id)
|
||||
)
|
||||
if inferred_intent == AGENT_INTENT_RECOMMEND:
|
||||
memories = await _recall_advisor_memories(
|
||||
request,
|
||||
@@ -405,7 +395,7 @@ async def chat_stream(
|
||||
db,
|
||||
advisor_id=user.id,
|
||||
customer_id=int(customer_id) if customer_id is not None else None,
|
||||
scope=chat_request.scope,
|
||||
scope="customer",
|
||||
question=chat_request.query,
|
||||
trace_id=trace_id,
|
||||
llm_client=getattr(_advisor_runtime(request), "llm_client", None),
|
||||
@@ -516,12 +506,17 @@ async def advisor_data_query(
|
||||
):
|
||||
"""查询当前投顾选中客户的数据,不返回 SQL,也不生成草稿。"""
|
||||
trace_id = _trace_id(request)
|
||||
customer_id, resolve_error = await _resolve_customer_from_query(
|
||||
db, advisor_id=user.id, query=body.query
|
||||
)
|
||||
if resolve_error or customer_id is None:
|
||||
return agent_failure(ERR_CODE_FORBIDDEN_CUSTOMER, resolve_error or "请在问题中补充客户编号或客户姓名", trace_id=trace_id)
|
||||
try:
|
||||
result = await execute_advisor_data_query(
|
||||
db,
|
||||
advisor_id=user.id,
|
||||
customer_id=body.customer_id,
|
||||
question=body.question,
|
||||
customer_id=customer_id,
|
||||
question=body.query,
|
||||
trace_id=trace_id,
|
||||
session_id=body.session_id,
|
||||
max_rows=body.max_rows,
|
||||
@@ -626,7 +621,11 @@ async def run_rebalance(
|
||||
db: AsyncSession = Depends(get_db),
|
||||
background_tasks: BackgroundTasks = None,
|
||||
):
|
||||
customer_id = body.customer_id
|
||||
customer_id, resolve_error = await _resolve_customer_from_query(
|
||||
db, advisor_id=user.id, query=body.query
|
||||
)
|
||||
if resolve_error or customer_id is None:
|
||||
return agent_failure(ERR_CODE_FORBIDDEN_CUSTOMER, resolve_error or "请在问题中补充客户编号或客户姓名", trace_id=_trace_id(request))
|
||||
relation = await ensure_customer_access(
|
||||
db, advisor_id=user.id, customer_id=int(customer_id)
|
||||
)
|
||||
@@ -657,34 +656,22 @@ async def fund_analysis(
|
||||
user: SysUser = Depends(audited_advisor),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
memories: list[dict] = []
|
||||
if body.customer_id is not None:
|
||||
await ensure_customer_access(
|
||||
db, advisor_id=user.id, customer_id=body.customer_id
|
||||
customer_id, resolve_error = await _resolve_customer_from_query(db, advisor_id=user.id, query=body.query)
|
||||
if resolve_error or customer_id is None:
|
||||
return agent_failure(ERR_CODE_FORBIDDEN_CUSTOMER, resolve_error or "请在问题中补充客户编号或客户姓名", trace_id=_trace_id(request))
|
||||
fund_codes = re.findall(r"[A-Za-z]{1,6}\d{3,8}", body.query.upper())
|
||||
if not fund_codes:
|
||||
return agent_failure(ERR_CODE_LLM_ERROR, "请在问题中补充基金代码", trace_id=_trace_id(request))
|
||||
memories = await _recall_advisor_memories(request, customer_id=customer_id, query=body.query)
|
||||
contexts = await load_fund_analysis_context(db, fund_codes=fund_codes)
|
||||
if not contexts:
|
||||
return _not_ready(request)
|
||||
if len(contexts) > 1:
|
||||
return agent_success(
|
||||
{"items": [build_fund_analysis(item["fund"], item["performance"]) for item in contexts]},
|
||||
trace_id=_trace_id(request),
|
||||
)
|
||||
memories = await _recall_advisor_memories(
|
||||
request,
|
||||
customer_id=body.customer_id,
|
||||
query=f"基金分析 {','.join(body.fund_codes)}",
|
||||
)
|
||||
fund = body.fund
|
||||
performance = body.performance
|
||||
if fund is None or performance is None:
|
||||
contexts = await load_fund_analysis_context(
|
||||
db,
|
||||
fund_codes=[str(code) for code in body.fund_codes],
|
||||
)
|
||||
if not contexts:
|
||||
return _not_ready(request)
|
||||
if len(contexts) == 1:
|
||||
fund = contexts[0]["fund"]
|
||||
performance = contexts[0]["performance"]
|
||||
else:
|
||||
return agent_success(
|
||||
{"items": [build_fund_analysis(item["fund"], item["performance"]) for item in contexts]},
|
||||
trace_id=_trace_id(request),
|
||||
)
|
||||
result = build_fund_analysis(fund, performance)
|
||||
result = build_fund_analysis(contexts[0]["fund"], contexts[0]["performance"])
|
||||
runtime = _advisor_runtime(request)
|
||||
if getattr(runtime, "llm_client", None) is not None:
|
||||
result["analysis_text"] = await generate_text(
|
||||
@@ -707,16 +694,25 @@ async def generate_talk_script(
|
||||
user: SysUser = Depends(audited_advisor),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
await ensure_customer_access(db, advisor_id=user.id, customer_id=body.customer_id)
|
||||
customer_id, resolve_error = await _resolve_customer_from_query(db, advisor_id=user.id, query=body.query)
|
||||
if resolve_error or customer_id is None:
|
||||
return agent_failure(ERR_CODE_FORBIDDEN_CUSTOMER, resolve_error or "请在问题中补充客户编号或客户姓名", trace_id=_trace_id(request))
|
||||
scene_type = TALK_SCENE_MARKET_FLUCTUATION
|
||||
if "投诉" in body.query:
|
||||
scene_type = TALK_SCENE_CUSTOMER_COMPLAINT
|
||||
elif "拦截" in body.query or "风控" in body.query:
|
||||
scene_type = TALK_SCENE_RISK_BLOCK_ORDER
|
||||
elif "调仓" in body.query or "偏离" in body.query:
|
||||
scene_type = TALK_SCENE_PORTFOLIO_DIVERGENCE
|
||||
memories = await _recall_advisor_memories(
|
||||
request,
|
||||
customer_id=body.customer_id,
|
||||
query=f"沟通话术 {body.scene_type}",
|
||||
customer_id=customer_id,
|
||||
query=body.query,
|
||||
)
|
||||
try:
|
||||
result = build_talk_script(
|
||||
body.scene_type,
|
||||
customer_name=body.customer_name,
|
||||
scene_type,
|
||||
customer_name="客户",
|
||||
)
|
||||
except ValueError as exc:
|
||||
raise ApiError(ERR_CODE_LLM_ERROR, str(exc)) from exc
|
||||
|
||||
Reference in New Issue
Block a user