在搭建 OPCwiki 多用户 AI 平台的过程中,最核心的技术挑战有两个:AI Agent 的动态调用链路和基于余额的精准计费系统。本文将分享完整的实践经验。
一、AI Agent 动态调用链路
1.1 核心架构
系统采用「管理员配置渠道 → 用户自动获取模型」的模式,完整调用链如下:
用户发起对话
→ chat_send() 检查余额
→ _get_model_config(user_id, model_id)
→ get_user_ai_models(user_id)
→ get_providers() // 从 providers.json 读取渠道列表
→ 返回 model_config = {
base_url, api_key, model, provider,
input_price_per_1m, // $/百万token 输入价格
output_price_per_1m // $/百万token 输出价格
}
→ chat(messages, model_config)
→ _cfg(model_config) // 自动检测 provider 类型
→ if provider == "hermes":
_hermes_chat(messages, config=model_config)
// 动态拼接 URL: base_url /chat/completions
// 动态使用 api_key model 参数
else:
POST {base_url}/chat/completions // OpenAI 兼容
1.2 关键实现细节
Provider 自动检测:系统支持 OpenAI 兼容、Hermes Agent、DeepSeek 等多种 API。通过以下逻辑自动识别:
if not cfg["provider"] or cfg["provider"] == "default":
is_hermes = (
"8642" in cfg["base_url"] or
"hermes-agent" in cfg["base_url"].lower() or
"hermes" in cfg["model"].lower() or
"api.opcgrow.org" in cfg["base_url"]
)
if is_hermes: cfg["provider"] = "hermes"
踩坑记录:早期版本 _hermes_chat() 写死了 http://127.0.0.1:8642/v1/chat/completions,导致管理后台配置的新地址完全不生效。修复后改为从 model_config 动态读取 base_url、api_key 和 model 参数,与 OpenAI 兼容 API 共享同一套路由逻辑。
二、计费系统设计
2.1 核心公式
2.2 完整计费链路
SSE 流式对话结束 (full_reply 收集完毕)
→ 估算 token 消耗:
input_tokens = sum(所有消息字符数) ÷ 4
output_tokens = len(full_reply) ÷ 4
→ bill_usage(user_id, model_config, input_tokens, output_tokens)
→ from services.storage import deduct_balance
→ deduct_balance(user_id, cost)
→ 从 users.json 读取 balance
→ 余额不足 → 返回 False
→ 余额充足 → 扣款并保存
2.3 防护机制
① 余额拦截:在 chat_send() 入口处检查余额,余额 ≤ 0 时返回 HTTP 402 并提示「余额不足,请点击左侧菜单购买配额充值」。
② 计费异常日志化:早期用 try/except: pass 吞噬了所有计费异常,导致余额不变也毫无察觉。修复后改为 yield f"[计费异常: {e}]" 直接在对话流中报错。
③ Token 估算:目前采用 4 字符 ≈ 1 token 的估算方式(对中英文混合场景基本准确),后续可改为从 OpenAI API 的 usage.prompt_tokens / usage.completion_tokens 精确取值。
2.4 价格配置
管理员在「管理后台 → 渠道/模型管理」中为每个渠道设定输入和输出价格($/百万token),系统自动分发给所有注册用户。例如:
| 模型 | 输入 ($/1M) | 输出 ($/1M) |
|---|---|---|
| DeepSeek V4 Flash | 0.308 | 0.616 |
| DeepSeek V4 Pro | 0.957 | 1.914 |
* 价格参考 API 官方定价,实际以管理后台配置为准
三、移动端响应式适配
为了让用户在手机上也能流畅使用,所有页面统一适配了响应式布局:
- 侧边栏覆层:移动端默认隐藏,点击左上角 ☰ 滑出,点击遮罩关闭
- CSS 断点:
@media (max-width: 768px),侧边栏 160px、字号 13px、卡片全宽 - 全部 14 个页面:顶级 div 统一加
page-container类自动适配 - 图表自适应:Canvas 元素在移动端自动缩放到父容器宽度
四、排查经验总结
🔧 黄金规则
- 源码编译通过 ≠ 容器内代码正确 — 90% 的 500 错误是容器跑旧代码
- 先用
docker exec验证容器内逻辑,再改源码 - 参考已正常工作的组件(如账单页参照资产配置页)
docker compose build --no-cache强制清缓存重建- Python
__pycache__必须删除后重启容器
—— 本文基于 OPCwiki v6 商业版实战经验整理 ——
评论区
0 条评论 · 评论需审核通过后显示
发表评论