14 KiB
14 KiB
瑞小美 AI 接入规范
适用于瑞小美全团队所有 AI 相关项目
最后更新:2026-01-17
核心原则
| 原则 | 要求 |
|---|---|
| 服务商策略 | 首选 4sapi.com → 备选 OpenRouter.ai(自动降级) |
| 统一配置 | 从门户系统统一获取 Key,各模块禁止独立配置 |
| 统一服务 | 通过 shared_backend.AIService 调用,禁止直接请求 API |
瑞小美 SCRM 配置入口
- 配置管理:https://scrm.ireborn.com.cn → AI 配置
- 调用统计:查看各模块 Token 使用量、成本、服务商分布
- 调用日志:按模块、服务商、状态筛选历史调用
服务商配置
降级策略(强制)
请求流程:4sapi.com → (失败) → OpenRouter.ai
| 优先级 | 服务商 | API 地址 | 说明 |
|---|---|---|---|
| 1(首选) | 4sapi.com | https://4sapi.com/v1/chat/completions |
国内优化,延迟低 |
| 2(备选) | OpenRouter.ai | https://openrouter.ai/api/v1/chat/completions |
模型全,稳定性好 |
降级触发条件(宽松策略,首选失败就尝试备选):
- 连接超时(默认 30s)
- 服务端错误(5xx)
- 客户端错误(4xx):余额不足、Key 无效、模型不存在等
- 网络异常
✅ 说明:只要首选服务商调用失败,就会自动尝试备选服务商
4sapi.com 配置
API 端点:
https://4sapi.com/v1/chat/completions
测试阶段 Key(仅限开发环境):
sk-9yMCXjRGANbacz20kJY8doSNy6Rf446aYwmgGIuIXQ7DAyBw
官方文档:
OpenRouter.ai 配置(备选)
API 端点:
https://openrouter.ai/api/v1/chat/completions
测试阶段 Key(仅限开发环境):
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
官方文档:Images | PDFs | Audio | Videos
Key 管理规范
⚠️ 强制要求
- 禁止在代码中硬编码 API Key
- 必须从门户系统统一获取配置
- 必须同时配置两个服务商的 Key(支持降级)
测试阶段 Key 见上方「服务商配置」章节
配置架构(瑞小美 SCRM)
┌───────────────────────────────────────────────────────────────┐
│ 门户系统 (scrm.ireborn.com.cn) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ AI 配置页面(仅超管可访问) │ │
│ │ - 首选服务商:4sapi.com(API Key + Base URL) │ │
│ │ - 备选服务商:OpenRouter(API Key + Base URL) │ │
│ │ - 默认模型 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ GET /api/ai/internal/config (内部 API,无需鉴权) │
└──────────────────────────────┬────────────────────────────────┘
│
┌───────────────────────┼───────────────────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 会话存档 │ │ 智能回复 │ │ 撩回搭子 │
│ AIService │ │ AIService │ │ AIService │
└─────────────┘ └─────────────┘ └─────────────┘
配置 API(门户系统已实现)
端点:GET http://portal-backend:8000/api/ai/internal/config
返回格式:
{
"code": 0,
"data": {
"primary": {
"provider": "4sapi",
"api_key": "sk-xxx...",
"base_url": "https://4sapi.com/v1"
},
"fallback": {
"provider": "openrouter",
"api_key": "sk-or-v1-xxx...",
"base_url": "https://openrouter.ai/api/v1"
},
"default_model": "gemini-3-flash-preview"
}
}
说明:
- 各模块通过 Docker 内网访问
portal-backend:8000 - 配置有 60 秒缓存,避免频繁调用
- 如需自定义端点,设置环境变量:
PORTAL_CONFIG_API=http://...
支持的能力
| 能力 | 方法 | 说明 |
|---|---|---|
| 文本聊天 | chat() |
基础对话,支持多轮 |
| 图片理解 | vision() |
PNG/JPEG/WebP/GIF |
| PDF 分析 | analyze_pdf() |
文档理解、OCR |
| 音频分析 | analyze_audio() |
语音转文字 |
| 视频分析 | analyze_video() |
视频内容理解 |
| 图像生成 | generate_image() |
文生图 |
| 流式输出 | chat_stream() |
逐字返回 |
官方文档见上方「服务商配置」章节
推荐模型
模型命名对照表
⚠️ 注意:两个服务商的模型命名规则不同,
AIService会自动转换
| 用途 | 4sapi.com(首选) | OpenRouter(备选) |
|---|---|---|
| 测试 | gemini-3-flash-preview ✅ |
google/gemini-3-flash-preview |
| 分析 | claude-opus-4-5-20251101-thinking ✅ |
anthropic/claude-opus-4.5 |
| 创意 | gemini-3-pro-preview ✅ |
google/gemini-3-pro-preview |
| 生图 | gemini-2.5-flash-image-preview ✅ |
google/gemini-2.0-flash-exp:free |
✅ 已验证可用(2026-01-17)
代码中使用
from shared_backend.services.ai_service import (
DEFAULT_MODEL, # 测试:自动映射到当前服务商
MODEL_ANALYSIS, # 分析
MODEL_CREATIVE, # 创意
MODEL_IMAGE_GEN, # 生图
)
# AIService 内部自动处理模型名转换,开发者无需关心
调用示例
基础用法
from shared_backend.services.ai_service import AIService
# module_code 标识你的模块,用于统计
ai = AIService(module_code="your_module", db_session=db)
# Key 自动从系统后台获取,无需手动指定
response = await ai.chat(
messages=[
{"role": "system", "content": "你是助手"},
{"role": "user", "content": "你好"}
],
prompt_name="greeting" # 必填,用于调用统计
)
print(response.content)
图片理解
response = await ai.vision(
prompt="描述这张图片",
images=["https://example.com/image.jpg"], # URL / base64 / bytes
prompt_name="image_analysis"
)
PDF 分析
response = await ai.analyze_pdf(
prompt="总结要点",
pdf="https://example.com/doc.pdf",
pdf_engine="pdf-text", # 免费 | "mistral-ocr" 收费
prompt_name="pdf_summary"
)
音频/视频
# 音频
response = await ai.analyze_audio(
prompt="转录并总结", audio=audio_bytes, mime_type="audio/mp3"
)
# 视频
response = await ai.analyze_video(
prompt="描述内容", video="https://example.com/video.mp4"
)
图像生成
response = await ai.generate_image(
prompt="一只橘猫",
model=MODEL_IMAGE_GEN,
prompt_name="cat_gen"
)
for img in response.images:
print(img)
流式输出
async for chunk in ai.chat_stream(messages, prompt_name="stream_test"):
print(chunk, end="", flush=True)
多模态消息格式
# 图片
{"type": "image_url", "image_url": {"url": "https://..." or "data:image/jpeg;base64,..."}}
# PDF
{"type": "file", "file": {"filename": "doc.pdf", "file_data": "..."}}
# 音频
{"type": "input_audio", "input_audio": {"url": "..."}}
# 视频
{"type": "input_video", "input_video": {"url": "..."}}
工具函数
from shared_backend.services.ai_service import (
file_to_base64, # 文件转 base64
make_data_url, # 构建 data URL
get_mime_type, # 获取 MIME 类型
)
返回结构
所有调用返回 AIResponse 对象(对服务商原始响应的统一封装):
@dataclass
class AIResponse:
content: str # ← choices[0].message.content
model: str # ← model
provider: str # ← 实际使用的服务商(4sapi / openrouter)
input_tokens: int # ← usage.prompt_tokens
output_tokens: int # ← usage.completion_tokens
total_tokens: int # ← 计算值
cost: float # ← usage.total_cost(如有)
latency_ms: int # ← 本地计算
raw_response: dict # ← 完整原始响应
images: List[str] # ← 图像生成结果
annotations: dict # ← PDF 解析注释
使用示例:
response = await ai.chat(messages, prompt_name="test")
print(response.content) # AI 回复
print(response.provider) # 实际服务商(4sapi / openrouter)
print(response.total_tokens) # 消耗 token
print(response.cost) # 费用(美元)
print(response.latency_ms) # 延迟(毫秒)
# 需要原始响应时
print(response.raw_response) # 服务商完整返回
提示词规范
文件位置(强制)
{模块}/后端服务/prompts/{功能名}_prompts.py
文件结构(强制)
"""功能描述"""
PROMPT_META = {
"name": "policy_analysis", # 唯一标识,用于统计
"display_name": "政策解读", # 后台显示名称
"description": "解析政策文档", # 功能描述
"module": "your_module", # 所属模块
"variables": ["content"], # 变量列表
}
SYSTEM_PROMPT = """你是专业分析师..."""
USER_PROMPT = """请分析:{content}"""
元数据自动注册(可视化)
PROMPT_META 会自动注册到数据库,实现后台可视化管理:
# 模块启动时扫描并注册
from shared_backend.services.ai_service import scan_and_register_prompts
scan_and_register_prompts(
module_path="/path/to/your_module",
module_code="your_module"
)
注册流程:
prompts/*_prompts.py → PROMPT_META → ai_prompts 表 → 后台可视化
后台功能:
- 查看所有已注册的提示词
- 按模块筛选
- 查看变量定义
- 点击"同步"手动刷新
提示词内容由开发维护(Git 版本控制),后台仅展示元数据,不支持在线编辑
调用日志与统计
⚠️ 强制要求
必须传入 db_session 才能记录调用日志到 ai_call_logs 表:
# ❌ 错误:无法记录日志,统计页面无数据
ai = AIService(module_code="my_module")
# ✅ 正确:日志会写入数据库
ai = AIService(module_code="my_module", db_session=db)
独立模块配置
如果模块运行在独立容器中,无法直接获取数据库会话,需配置环境变量:
# docker-compose.yml
environment:
- DATABASE_URL=mysql+pymysql://user:pass@scrm-mysql:3306/scrm_content?charset=utf8mb4
然后在代码中自动创建会话:
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
import os
def get_db_session():
database_url = os.getenv("DATABASE_URL")
if not database_url:
return None
engine = create_engine(database_url, pool_pre_ping=True)
Session = sessionmaker(bind=engine)
return Session()
# 使用
db = get_db_session()
ai = AIService(module_code="my_module", db_session=db)
查看统计
入口:https://scrm.ireborn.com.cn → AI 配置 → 调用统计
统计维度:
- 按模块:各模块调用次数、Token 消耗、成本
- 按服务商:4sapi / OpenRouter 使用分布(观察降级频率)
- 按日期:调用趋势图
自动记录字段(ai_call_logs 表):
| 字段 | 说明 |
|---|---|
module_code |
模块标识 |
prompt_name |
提示词名称 |
provider |
实际使用的服务商(4sapi / openrouter) |
model |
使用的模型 |
input_tokens / output_tokens |
Token 消耗 |
cost |
费用(美元) |
latency_ms |
响应延迟 |
status |
调用状态(success / error) |
error_message |
错误信息(失败时) |
created_at |
调用时间 |
降级监控:通过 provider 字段筛选,可观察降级发生频率,评估首选服务商稳定性
检查清单
配置检查(门户系统)
- 在门户 AI 配置页面配置 4sapi.com API Key
- 在门户 AI 配置页面配置 OpenRouter API Key(备选)
- 确认两个 Key 都有效(门户页面显示"已配置")
代码检查(各模块)
- 使用
shared_backend.AIService,未直接调用 API - 未硬编码 API Key
- 创建
prompts/{功能}_prompts.py - 包含
PROMPT_META(name, display_name, module, variables) - 调用时传入
prompt_name(用于统计) - 初始化时传入
db_session(记录日志)
验证
# 检查门户配置 API 是否可访问
curl http://portal-backend:8000/api/ai/internal/config
# 检查 AI 调用日志是否记录
SELECT * FROM ai_call_logs ORDER BY created_at DESC LIMIT 10;
瑞小美 AI 团队 · 2026-01-17