|
@@ -4,14 +4,24 @@
|
|
|
(multipart 入参、SSE 帧格式、thread_id ≡ session_id、错误码语义),这样 1.5
|
|
(multipart 入参、SSE 帧格式、thread_id ≡ session_id、错误码语义),这样 1.5
|
|
|
的前端不用改一行就能连上。
|
|
的前端不用改一行就能连上。
|
|
|
|
|
|
|
|
-与 1.5 的差异只有两处,都在实现层而非契约层:
|
|
|
|
|
-
|
|
|
|
|
-1. **不做鉴权**:1.5 用 ``Depends(get_current_user)`` 校验 ``x-access-token``
|
|
|
|
|
- 并解析出用户;2.0 直接取 multipart 的可选字段 ``user_name``(缺省
|
|
|
|
|
- ``default``)。风险是客户端可自报身份,仅适用于内网/开发期——上线前
|
|
|
|
|
- 把 ``_resolve_user`` 换成真实的 ``Depends`` 即可,其余代码不用动。
|
|
|
|
|
-2. **没有意图识别**:1.5 曾经按意图分流到不同的 agent,后来也收敛成了单一
|
|
|
|
|
- dialog agent。2.0 直接就是单一 agent。
|
|
|
|
|
|
|
+与 1.5 的差异有三处:
|
|
|
|
|
+
|
|
|
|
|
+1. **不做鉴权**(实现层):1.5 用 ``Depends(get_current_user)`` 校验
|
|
|
|
|
+ ``x-access-token`` 并解析出用户;2.0 直接取 multipart 的可选字段
|
|
|
|
|
+ ``user_name``(缺省 ``default``)。风险是客户端可自报身份,仅适用于
|
|
|
|
|
+ 内网/开发期——上线前把 ``_resolve_user`` 换成真实的 ``Depends`` 即可,
|
|
|
|
|
+ 其余代码不用动。
|
|
|
|
|
+2. **没有意图识别**(实现层):1.5 曾经按意图分流到不同的 agent,后来也
|
|
|
|
|
+ 收敛成了单一 dialog agent。2.0 直接就是单一 agent。
|
|
|
|
|
+3. **删掉了 ``POST /api/chat/only``**(契约层,唯一一处收缩):1.5 的这个
|
|
|
|
|
+ 端点与 ``/chat`` 除了流水上的 ``kind`` 标签外**行为完全相同**,而那个标签
|
|
|
|
|
+ 没有任何消费方(不聚合、不分账、不影响额度)。1.5 自己也为这份重复付过
|
|
|
|
|
+ 代价——见 AGENTS.md §六「为什么没有 /chat/only」。1.5 前端从未调用过它。
|
|
|
|
|
+ 若将来确有按渠道分账的需求,应当**先把聚合/额度按渠道拆开**,再引入入口,
|
|
|
|
|
+ 而不是先立一个行为相同的端点。
|
|
|
|
|
+
|
|
|
|
|
+ 保留 ``/chat`` 之外的另两个入口 ``/chat/resume`` 与 ``/chat/interrupt``:
|
|
|
|
|
+ 它们承载的是**不同能力**(中断恢复、挂起查询),不是同一能力的别名。
|
|
|
"""
|
|
"""
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
from __future__ import annotations
|
|
@@ -288,30 +298,6 @@ async def chat(
|
|
|
mode=mode,
|
|
mode=mode,
|
|
|
file=file,
|
|
file=file,
|
|
|
user_name=_resolve_user(user_name),
|
|
user_name=_resolve_user(user_name),
|
|
|
- billing_kind="chat",
|
|
|
|
|
- trace_id=_trace_id_of(request),
|
|
|
|
|
- )
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-@router.post("/chat/only")
|
|
|
|
|
-async def chat_only(
|
|
|
|
|
- message: str = Form(...),
|
|
|
|
|
- session_id: str | None = Form(default=None),
|
|
|
|
|
- thread_id: str | None = Form(default=None),
|
|
|
|
|
- mode: str | None = Form(default=None),
|
|
|
|
|
- file: UploadFile | None = File(default=None),
|
|
|
|
|
- user_name: str | None = Form(default=None),
|
|
|
|
|
- request: Request = None,
|
|
|
|
|
-):
|
|
|
|
|
- """纯对话入口。管线与 /chat 完全相同,只有计费类型不同(便于分账)。"""
|
|
|
|
|
- return await _run_chat_pipeline(
|
|
|
|
|
- message=message,
|
|
|
|
|
- session_id=session_id,
|
|
|
|
|
- thread_id=thread_id,
|
|
|
|
|
- mode=mode,
|
|
|
|
|
- file=file,
|
|
|
|
|
- user_name=_resolve_user(user_name),
|
|
|
|
|
- billing_kind="chat_only",
|
|
|
|
|
trace_id=_trace_id_of(request),
|
|
trace_id=_trace_id_of(request),
|
|
|
)
|
|
)
|
|
|
|
|
|
|
@@ -323,10 +309,9 @@ async def _run_chat_pipeline(
|
|
|
mode: str | None,
|
|
mode: str | None,
|
|
|
file: UploadFile | None,
|
|
file: UploadFile | None,
|
|
|
user_name: str,
|
|
user_name: str,
|
|
|
- billing_kind: str,
|
|
|
|
|
trace_id: str = "",
|
|
trace_id: str = "",
|
|
|
):
|
|
):
|
|
|
- """/chat 与 /chat/only 的公共管线。
|
|
|
|
|
|
|
+ """对话入口的公共管线。
|
|
|
|
|
|
|
|
步骤顺序与原由:
|
|
步骤顺序与原由:
|
|
|
0. 额度预检 —— 在开任何资源之前 fail-closed 拦掉超限用户
|
|
0. 额度预检 —— 在开任何资源之前 fail-closed 拦掉超限用户
|
|
@@ -336,6 +321,10 @@ async def _run_chat_pipeline(
|
|
|
4. 上传落盘 —— 存进 agent 可读的沙箱
|
|
4. 上传落盘 —— 存进 agent 可读的沙箱
|
|
|
5. 消息拼装 —— 文件说明 + 引用 + 技能 + 偏好 + 模式指令
|
|
5. 消息拼装 —— 文件说明 + 引用 + 技能 + 偏好 + 模式指令
|
|
|
6. 并发闸 + SSE 装配
|
|
6. 并发闸 + SSE 装配
|
|
|
|
|
+
|
|
|
|
|
+ 不再是「多入口的公共管线」:``/chat/only`` 已删除(理由见模块 docstring),
|
|
|
|
|
+ 现在只有 ``/chat`` 走这里。保留这层函数是因为它把管线步骤与 FastAPI 的
|
|
|
|
|
+ 参数声明分开了——将来再加同族入口时不必把它拆回来。
|
|
|
"""
|
|
"""
|
|
|
started_at = db_conn.now()
|
|
started_at = db_conn.now()
|
|
|
usage_day = db_conn.day_key(started_at)
|
|
usage_day = db_conn.day_key(started_at)
|
|
@@ -391,7 +380,10 @@ async def _run_chat_pipeline(
|
|
|
config=graph_config,
|
|
config=graph_config,
|
|
|
message=final_message,
|
|
message=final_message,
|
|
|
user_name=user_name,
|
|
user_name=user_name,
|
|
|
- kind=billing_kind,
|
|
|
|
|
|
|
+ # 计费渠道标签。取值集合:chat(本入口)| resume(中断恢复)
|
|
|
|
|
+ # | scheduled(定时任务)。没有 chat_only——那个入口已删除,
|
|
|
|
|
+ # 因为它的标签不承载任何行为差异(见模块 docstring 差异 3)。
|
|
|
|
|
+ kind="chat",
|
|
|
model=config.MODEL,
|
|
model=config.MODEL,
|
|
|
original_user_message=ref["original"] or message,
|
|
original_user_message=ref["original"] or message,
|
|
|
trace_id=trace_id,
|
|
trace_id=trace_id,
|