pipeline-llm/wwwroot/api/v1/chat/completions.dspy

80 lines
3.1 KiB
Plaintext
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.

# completions.dspy — OpenAI 兼容 LLM 推理端点(产线平台统一模型入口,分类照 llmage)
#
# URL: /pipeline_llm/api/v1/chat/completions
# OpenAI 兼容客户端配置:
# base_url = http://<host>/pipeline_llm/api/v1
# api_key = <短期 token>(pipeline_llm_tokens 签发,非真实模型 key)
#
# 鉴权:Authorization: Bearer *** token>,不依赖登录会话(运行环境无 session)。
# 机构隔离:按 token 绑定的 org_id 走治理链解析真实模型与 key,真 key 不出服务进程。
#
# 调用链:token 校验 → chat_inference(门禁链①-⑥+预授权)→ 上游调用 → 结算(双维度记账)。
# 失败返回 OpenAI 错误结构,消息真实可行动。
auth = ''
try:
auth = request.headers.get('Authorization', '') or ''
except Exception:
auth = ''
if not auth:
auth = (params_kw or {}).get('api_key', '') or ''
if not auth:
return json.dumps({"error": {"message": "缺少 Authorization Bearer token",
"type": "invalid_request_error", "code": "missing_token"}},
ensure_ascii=False)
payload = None
try:
payload = await request.json()
except Exception:
payload = None
if not isinstance(payload, dict):
try:
_raw = await request.text()
payload = json.loads(_raw) if _raw else None
except Exception:
payload = None
if not isinstance(payload, dict):
_pk = dict(params_kw or {})
_msgs = _pk.get('messages')
if isinstance(_msgs, str):
try:
_msgs = json.loads(_msgs)
except Exception:
_msgs = None
payload = {"model": _pk.get('model', ''), "messages": _msgs} if _msgs else None
if not isinstance(payload, dict) or not payload.get('messages'):
return json.dumps({"error": {"message": "请求体缺 messages",
"type": "invalid_request_error", "code": "missing_messages"}},
ensure_ascii=False)
# token 校验(沿用现有短期 token 机制:签发/校验/吊销/机构隔离齐全)
ok, info = await verify_llm_token(auth)
if not ok:
return json.dumps({"error": {"message": str(info),
"type": "invalid_request_error", "code": "invalid_token"}},
ensure_ascii=False)
org_id = info.get('org_id', '') or ''
user_id = info.get('created_by', '') or ''
# token 绑定 model_name 则强制(防运行环境越权指定贵模型);否则用请求里的 model
task_ref = 'v1:%s' % (info.get('project_id') or '')
try:
data = await llm_chat_inference(
org_id, user_id, payload,
model_name=(info.get('model_name') or payload.get('model') or ''),
task_ref=task_ref)
# 回填 token 用量
try:
await record_llm_token_usage(info.get('id', ''), data.get('usage') or {})
except Exception:
pass
return json.dumps(data, ensure_ascii=False, default=str)
except Exception as e:
return json.dumps({"error": {"message": str(e),
"type": "invalid_request_error", "code": "govern_error"}},
ensure_ascii=False)