集成概述
DJWork(DJWork 智能AI应用平台)对外提供一套完整的 REST API,第三方业务系统(OA、合同管理、招投标、案卷管理等)可以通过它把合同审核、要素提取、文档比对、智能脱敏、印章核验、NJCA 审核、知识库问答等 AI 能力嵌入自己的业务流程,也可以免登嵌入现成页面。
开放能力全景
flowchart LR
BIZ[业务系统] -->|组织 Key djk_| AUTH[用户与凭证
/api/v1/token]
AUTH -->|用户 JWT| AUDIT[合同审核]
AUTH --> EXT[要素提取]
AUTH --> CMP[文档比对]
AUTH --> RDT[智能脱敏]
AUTH --> SEAL[印章核验]
AUTH --> NJCA[NJCA 审核]
AUTH --> KB[知识库问答]
AUTH --> LLM[LLM 网关
OpenAI 兼容]
AUTH --> OCR[OCR 代理]
AUTH -.->|MCP 协议| MCPS[MCP 服务 /mcp/djwork
18 个工具]
AUTH -.->|scope=page| SSO[页面免登 /sso/enter]
接入前准备
- 申请组织 API Key。联系管理员在「管理界面 → 组织管理」为你的系统创建接入记录,签发
djk_前缀的组织 API Key。Key 由api_id和secret两段组成,明文只在创建时展示一次,请立即妥善保存。 - 确认权限范围。每个 Key 按模块授权:users(用户管理)、audit(审核)、compare(比对)、extract(提取)、kb(知识库)、redact(脱敏)、ocr、llm、files、agent、seal_verify(印章核验)、njca_audit(NJCA 审核)。按最小可用原则申请,越权访问会返回 403 并记入审计日志。
- 约定用户标识。确定用你系统里的什么字段作为
user_id(工号 / 手机号 / UUID 均可),它会在 DJWork 侧映射为平台用户,用于配额、数据隔离与审计。 - 确认网络与白名单。获取 DJWork 服务地址(默认端口 8000);如需页面嵌入,提前与管理员确认跳转白名单与 Referer 域名白名单。
三种接入形态
形态一:纯接口集成
你的后端服务器调用 DJWork API,拿到结构化结果后回传到自己的界面。适合只需要结果数据的场景,例如在 OA 的合同审批单里展示"AI 审核得分 + 问题清单"。
形态二:页面嵌入(SSO 免登)
为用户签发带 page scope 的 Token,通过 /sso/enter 免登跳转或 iframe 嵌入 DJWork 的完整页面(审核报告、任务列表、知识引擎等)。适合希望直接复用现成界面、不做二次开发的场景。
形态三:MCP 工具调用
如果你的系统已接入 AI Agent(Claude、Cursor、自研智能体),可把 DJWork 的 MCP 服务挂为工具源:Agent 自动发现并调用合同审核、智能提取、文档比对、印章核验、NJCA 审核等 18 个工具,无需逐个封装 REST 接口。详见下方「MCP 接入」。
统一约定
| 项 | 说明 |
|---|---|
| Base URL | http(s)://<host>:8000,请求与响应均为 UTF-8 JSON(文件上传为 multipart/form-data) |
| 认证头 | Authorization: Bearer <凭证>(组织 Key 或用户 JWT) |
| 分页 | ?page=1&per_page=10,响应含 {total, page, per_page, pages} |
| 时间格式 | ISO 8601(如 2026-09-03T10:00:00) |
| 错误格式 | 统一 {"detail": "<原因>"},HTTP 状态码表意见「错误处理」 |
| 文件限制 | 单文件 ≤ 50MB;审核支持 .docx / .pdf,比对支持 PDF / 图片 / DOCX,脱敏目前仅 PDF |
| 异步模式 | 审核、比对、提取、脱敏均为「提交任务 → 轮询进度 → 取结果」三段式,建议 2–3 秒轮询 |
| 审计 | 每次 API 调用记录访问日志,管理员可在后台按系统 / 用户 / 时间检索 |
认证与鉴权
系统采用「组织 Key + 用户 JWT」两级凭证体系:组织 Key 标识接入方系统,用于用户管理与签发凭证;用户 JWT 承载日常业务调用,实现按用户的配额控制、数据隔离与操作审计。
凭证签发流程
sequenceDiagram
autonumber
participant Biz as 业务系统
participant API as DJWork API
participant DB as 平台数据库
Biz->>API: POST /api/v1/token(组织 Key + user_id)
API->>DB: 查找用户(组织 + external_user_id)
alt 用户不存在且组织允许自动注册
API->>DB: 自动注册 ext_组织code_用户ID
else 用户存在
API->>DB: 校验 is_active / is_frozen
end
API-->>Biz: { token, expires_in, registered, user }
Note over Biz: 缓存 Token,到期前静默换证
凭证类型
| 凭证 | 格式 | 适用 |
|---|---|---|
| 组织 API Key | djk_<api_id>.<secret> | 用户生命周期接口(/api/v1/users*)、签发用户 Token;也可直连印章核验 / NJCA 审核接口(请求中带 user_id) |
| 用户 JWT | HS256 JWT | 全部业务接口 + SSO 页面免登 |
| 个人密钥 | dkp_... | 用户在个人中心自行创建,等同本人 JWT(业务 API + SSO),适合用户级脚本调用 |
| 管理员 JWT | 后台登录签发 | 仅 /api/admin/* 管理接口 |
签发用户 Token
POST/api/v1/token —— 用组织 Key 为终端用户签发 JWT:
| 字段 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
user_id | string | 是 | — | 业务系统用户唯一标识(工号 / 手机号 / UUID) |
nickname | string | 否 | — | 昵称,首次注册时写入 |
email | string | 否 | — | 邮箱,首次注册时写入 |
expires_in | int | 否 | 86400 | 有效期秒数,60 ~ 31536000(最长 365 天);SSO 跳转建议 300 秒短时效 |
scope | string | 否 | api,page | api=仅接口调用;page=含页面免登 |
curl -X POST https://<host>:8000/api/v1/token \
-H "Authorization: Bearer djk_<api_id>.<secret>" \
-H "Content-Type: application/json" \
-d '{"user_id":"10086","nickname":"张三","expires_in":86400}'
{
"token": "eyJhbGciOiJIUzI1NiIs...",
"token_type": "bearer",
"expires_in": 86400,
"registered": false,
"user": {
"id": 42,
"username": "ext_erpsap_10086",
"external_user_id": "10086",
"is_active": true,
"is_frozen": false
}
}
registered=true表示本次自动注册了新用户;组织关闭auto_register时需先调POST /api/v1/users预创建。- 用户被冻结(
is_frozen)后已签发的 JWT 即时失效,业务接口返回 403。
调用业务接口
import requests
BASE = "http://<host>:8000"
# 1. 组织 Key 换取用户 JWT(可缓存复用)
r = requests.post(f"{BASE}/api/v1/token",
headers={"Authorization": "Bearer djk_<组织Key>"},
json={"user_id": "10086"})
token = r.json()["token"]
H = {"Authorization": f"Bearer {token}"}
# 2. 用用户 JWT 调用业务接口(以查询合同类型为例)
types = requests.get(f"{BASE}/api/contract-types", headers=H).json()
用户生命周期管理
| 端点 | 说明 |
|---|---|
GET/api/v1/users | 用户列表(page/per_page/status/q) |
POST/api/v1/users | 预创建用户(user_id 必填,可设 quota 审核配额) |
GETPUTDELETE/api/v1/users/{user_id} | 查询 / 更新 / 删除(级联清理业务数据) |
POST/api/v1/users/{user_id}/status | 冻结 / 解冻 {frozen: true|false},即时阻断 JWT |
POST/api/v1/users/{user_id}/token | 为该用户重发凭证 |
GET/api/v1/users/{user_id}/data | 用户数据概览(任务 / 文件 / 知识库 / 用量) |
GET/api/v1/usage | 组织维度用量统计 |
最佳实践
- 缓存 Token:同一用户在有效期内复用 JWT;收到 401 或临近过期时,用
POST /api/v1/token静默换新,不要每次请求都签发。 - 最小 scope:纯后端集成只申请
api;需要嵌入页面才加page。 - 短时效 + 换证:高安全场景给
expires_in=300,由后端定时换证,Token 泄露风险窗口最小。 - 区分 401 / 403:401 是凭证问题(换证重试一次),403 是权限 / 冻结 / 配额问题(提示用户,不要重试)。
SSO 免登集成
为用户签发含 page scope 的 Token 后,用一条 URL 即可让用户免登录进入 DJWork 的任意页面,也支持 iframe 嵌入第三方门户。落地后 Token 会被写入页面登录态(localStorage.jwt_token),后续走站内正常会话。
免登流程
sequenceDiagram
autonumber
participant Biz as 业务系统(门户/iframe)
participant SSO as DJWork /sso/enter
participant Page as 目标页面
Biz->>Biz: POST /api/v1/token
(expires_in=300, scope=page)
Biz->>SSO: GET /sso/enter?token=xxx&redirect=/tasks
SSO->>SSO: 校验 scope 含 page
SSO->>SSO: 校验 redirect 在白名单内
SSO->>SSO: 校验 Referer 域名白名单(iframe 场景)
SSO-->>Page: 写入登录态并 302 到 /tasks
跳转 URL
https://<host>:8000/sso/enter?token=<用户JWT>&redirect=/tasks
| 参数 | 说明 |
|---|---|
token | 含 page scope 的用户 JWT(或 dkp_ 个人密钥),必须经 URL 传递 |
redirect | 登录后落地的站内路径,如 /tasks、/upload、/knowledge-engine、/kb,需在组织跳转白名单内(支持 * 通配任意站内路径) |
iframe 嵌入
<iframe
src="https://<host>:8000/sso/enter?token=<JWT>&redirect=/tasks"
style="width:100%;height:900px;border:0">
</iframe>
嵌入时 DJWork 会校验请求的 Referer 是否在组织的域名白名单内,白名单外的页面会被拒绝,请提前向管理员登记你的门户域名。
推荐落地页
| 落地页 | 路径 | 适合场景 |
|---|---|---|
| 上传审核 | /upload | 让用户直接发起合同审核 |
| 任务列表 | /tasks | 查看该用户全部审核任务与进度 |
| 智能应用 | /smart-apps | 提取 / 比对 / 脱敏 / 印章 / NJCA 工具入口 |
| 知识引擎 | /knowledge-engine | 基于知识库的 AI 问答 |
| 知识库 | /kb | 知识库管理 |
安全约束
redirect只允许白名单内的站内路径,不能跳转外部网站。- SSO 场景建议单独签发短时效 Token(
expires_in: 300+scope: page),页面加载完成即换取登录态,暴露窗口最小。 - 历史的一次性票据接口
POST /api/v1/ticket已软弃用(返回 410),请统一使用 Token 直跳。
合同审核集成
最常用的集成能力。整体为「提交任务 → 轮询进度 → 拉取结果 → 下载批注文档」四步,全部使用用户 JWT。文件解析、OCR、多轮 LLM 审核都在后台异步执行。
交互时序
sequenceDiagram
autonumber
participant Biz as 业务系统
participant API as DJWork API
participant W as Celery Worker
Biz->>API: POST /api/tasks/submit(文件 + 参数)
API-->>Biz: { tasks: [{ task_id, file_id, file_name }] }
loop 轮询(2~3 秒)
Biz->>API: GET /api/tasks/{task_id}/status
API-->>Biz: { status: running, progress: 60 }
end
Biz->>API: GET /api/tasks/{task_id}/detail
API-->>Biz: { score, issues[], ... }
Biz->>API: GET /api/tasks/{task_id}/download
API-->>Biz: 文件流(带批注报告)
第一步:提交审核任务
POST/api/tasks/submit(multipart/form-data)
| 字段 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
files | file[] | 是 | — | .docx / .pdf,单文件 ≤50MB,一次 1~5 个 |
contract_type_code | string | 是 | — | 合同类型编码,来自 GET /api/contract-types |
stance | string | 是 | — | party_a(甲方)/ party_b(乙方)/ neutral(中立) |
intensity | string | 是 | — | quick(单轮)/ standard(两轮+反思)/ deep(多轮+交叉验证) |
concurrency | int | 否 | 1 | 并发审核数 1~5(多文件时生效) |
force_reaudit | bool | 否 | false | 强制重审(忽略相同文件秒传) |
curl -X POST https://<host>:8000/api/tasks/submit \
-H "Authorization: Bearer <用户JWT>" \
-F "files=@合同.docx" \
-F "contract_type_code=sale" \
-F "stance=party_a" \
-F "intensity=standard"
{
"tasks": [
{ "task_id": "a1b2c3d4", "file_id": "f9e8d7c6", "file_name": "合同.docx" }
]
}
第二步:轮询进度
GET/api/tasks/{task_id}/status,建议每 2–3 秒一次:
{ "task_id": "a1b2c3d4", "status": "running", "progress": 60,
"message": "AI 审核中" }
{ "task_id": "a1b2c3d4", "status": "completed", "progress": 100,
"result": { "file_id": "f9e8d7c6", "score": 78, "total_issues": 6 } }
status状态机:pending → queued → running → completed | failed。- 扫描版 / 图片型 PDF 会先 OCR 再审核,可能持续数分钟,轮询超时建议放宽到 10 分钟以上。
- 另有进度轮询
GET /api/tasks/{task_id}/progress?access_token=<JWT>和日志 SSEGET /api/tasks/{task_id}/log/sse?access_token=<JWT>可选(均需用户 JWT,进度端点仅限任务归属者)。
第三步:获取审核结果
GET/api/tasks/{task_id}/detail 返回完整结果:
score:合同风险评分(AI 综合评定)。issues[]:逐条问题,含风险等级(高 / 中 / 低)、条款维度(如"违约责任条款")、原文定位、问题说明与修改建议。extracted_fields:本次审核顺带抽取的关键要素。
第四步:下载批注文档
GET/api/tasks/{task_id}/download 返回把问题以批注形式写回原文的文件(优先带批注 PDF,其次 DOCX),可直接转存到你的业务附件里。
完整 Python 示例
import time
import requests
BASE = "http://<host>:8000"
H = {"Authorization": "Bearer <用户JWT>"}
# 1. 提交
r = requests.post(f"{BASE}/api/tasks/submit", headers=H,
files={"files": open("合同.docx", "rb")},
data={"contract_type_code": "sale", "stance": "party_a",
"intensity": "standard"}).json()
task_id = r["tasks"][0]["task_id"]
# 2. 轮询(最长 10 分钟)
deadline = time.time() + 600
while time.time() < deadline:
s = requests.get(f"{BASE}/api/tasks/{task_id}/status", headers=H).json()
print(s["status"], s["progress"])
if s["status"] in ("completed", "failed"):
break
time.sleep(3)
if s["status"] != "completed":
raise RuntimeError(s.get("error") or "审核超时")
# 3. 结果与批注文档
detail = requests.get(f"{BASE}/api/tasks/{task_id}/detail", headers=H).json()
print("评分:", detail["score"], "问题数:", detail["total_issues"])
pdf = requests.get(f"{BASE}/api/tasks/{task_id}/download", headers=H)
open("审核报告_带批注.pdf", "wb").write(pdf.content)
GET /api/v1/users/{user_id} 查配额,或在界面提前置灰提交按钮。其他能力集成
除合同审核外,其余能力同样遵循「提交 → 轮询 → 取结果」模式,可以直接复用同一套任务轮询封装。本页给出各能力的关键步骤与参数;逐字段定义见「API 文档」。
要素提取
- GET
/api/extractions/templates获取提取模板(内置合同模板含甲乙方、金额、期限、付款方式等字段 schema,管理员可自定义)。 - POST
/api/uploads/quick上传文件(multipart字段file),得到file_id。 - POST
/api/extractions/quick提交file_id+template_id,发起异步提取。 - 轮询 GET
/api/extractions/{file_id}/status,完成后 GET/api/extractions/{file_id}/detail获取逐字段抽取结果(含字段值与依据位置)。
文档比对
flowchart LR
U1[上传 source
POST /api/doc-compare/upload] --> U2[上传 target
role=target]
U2 --> S[启动比对
POST /api/doc-compare/start]
S --> P[进度轮询
GET .../progress]
P --> R[差异清单
GET .../result
逐页 + 统计]
- 上传时用
role区分source(原稿)/target(对照稿),两份文件类型需一致(PDF vs 图片 vs DOCX)。 - 结果
page_diffs[]按页给出差异类型(added/deleted/modified)与前后内容,stat汇总三类数量。
智能脱敏
- POST
/api/redact/upload上传 PDF,得到file_id。 - POST
/api/redact/scan发起扫描:profile选规则集(contract合同 /case案卷 /all),detect_seals可选同时检测印章。任务进入scanning→reviewing。 - GET
/api/redact/{task_id}/detail拉取分组候选敏感项(字段、原文、页码、置信度),在你的界面呈现复核清单。 - POST
/api/redact/apply提交复核结论:blacklist(抹除)/whitelist(保留)、date_mode(日期涂至季度 / 整年 / 不处理)、replacements(替换值)、manual_rects(人工框选补涂)等。 - 轮询
/status至完成,检查verify_result.remaining(残留数应为 0),再取/result脱敏副本与/report脱敏报告。
verify_result: {total, remaining} 可直接用于你侧的质量卡点。印章核验与 NJCA 审核(双通道)
这两个模块提供 /api/v1 单接口通道:组织 Key 直接调用(请求中带 user_id),无需先签发用户 JWT;用用户 JWT 调用亦可。
import requests, time
BASE = "http://<host>:8000"
KH = {"Authorization": "Bearer djk_<组织Key>"}
# 1. 创建核验任务(组织 Key 通道必带 user_id)
r = requests.post(f"{BASE}/api/v1/seal-verifications",
headers=KH, data={"user_id": "10086"},
files={"file": open("盖章页.pdf", "rb")}).json()
task_id = r["data"]["task_id"]
# 2. 轮询结果
while True:
s = requests.get(f"{BASE}/api/v1/seal-verifications/{task_id}",
headers=KH).json()
if s["data"]["status"] in ("completed", "failed"):
break
time.sleep(3)
# 3. 逐页印章明细:文字 / 类型 / 坐标 / 匹配状态
for page in s["data"]["result"]["pages"]:
for seal in page["seals"]:
print(seal["text"], seal["seal_type"], seal["match_status"])
NJCA 审核把 files[] 批量上传到 POST /api/v1/njca-audits,轮询 GET /api/v1/njca-audits/{task_id} 后得到 conclusion(通过 / 不通过 / 无法判定)、fail_reasons 与要素抽取明细(被授权人、证件有效期、委托单位、印章匹配等)。
知识库与 LLM 网关
- 知识库:POST
/api/kb建库 →POST /api/kb/{kb_id}/documents上传文档(自动解析、分片、向量化)→POST /api/kb/search问答(返回answer+ 引用chunks),或用/api/kb/search/stream做 SSE 流式。 - OpenAI 兼容网关:
POST /llm/v1/chat/completions在标准 OpenAI 协议上扩展kb_ids/kb_top_k/web_search,任何 OpenAI SDK 只改base_url即可获得「RAG + 联网搜索」。
from openai import OpenAI
client = OpenAI(base_url="http://<host>:8000/llm/v1",
api_key="<用户JWT>")
resp = client.chat.completions.create(
model="deepseek-v4-flash",
messages=[{"role": "user", "content": "电子签章流程是怎么设置的?"}],
extra_body={"kb_ids": [2], "kb_top_k": 5}, # DJWork 扩展参数
stream=False)
print(resp.choices[0].message.content)
MCP 接入
DJWork 把内置能力以 MCP(Model Context Protocol)工具开放:已接入 AI Agent 的系统(Claude、Cursor、自研智能体)把 DJWork 挂为 MCP 工具源后,Agent 即可自动发现并调用合同审核、智能提取、文档比对、印章核验、NJCA 审核、知识库、OCR、LLM 等 18 个工具,无需逐个封装 REST 接口。
端点与认证
| 项 | 说明 |
|---|---|
| 端点 | POST /mcp/djwork/(建议带尾斜杠,避免 307 跳转) |
| 传输 | MCP Streamable HTTP,无状态模式(服务端多副本部署,无需会话粘滞) |
| 认证 | Authorization: Bearer <令牌>——支持两种令牌:① dkp_ 个人 API 密钥(个人中心创建,长期有效,推荐写进客户端配置);② 用户 JWT(组织 Key 经 /api/v1/token 换证,短期) |
| 权限 | 按用户角色裁剪:admin_* / redact_* 仅管理员可见;印章核验、NJCA 审核工具按智能应用授权校验(admin / CRM 认证 / 单独授权),计次与页面入口合并 |
客户端一键配置
先在 DJWork 个人中心 → API 密钥 新建一个个人密钥(dkp_ 开头,长期有效),替换下方配置里的占位密钥即可。配置里其余内容已写好,点右上角「复制」直接粘贴到对应客户端的 MCP 配置文件:
Claude Desktop / Cursor / 通用 mcpServers
{
"mcpServers": {
"djwork": {
"type": "http",
"url": "https://djwork.njca.com.cn/mcp/djwork/",
"headers": {
"Authorization": "Bearer dkp_替换为你的个人API密钥"
}
}
}
}
Claude Desktop 写入 claude_desktop_config.json;Cursor 写入 ~/.cursor/mcp.json(或设置 → MCP → Add server);Cline / 其他兼容客户端同名结构。私有部署把 url 换成自己的域名即可。
仅支持 stdio 的客户端(mcp-remote 桥接)
客户端不支持 HTTP 传输时,用官方 mcp-remote 桥接(需本机 Node.js ≥ 18):
{
"mcpServers": {
"djwork": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://djwork.njca.com.cn/mcp/djwork/",
"--header",
"Authorization: Bearer dkp_替换为你的个人API密钥"
]
}
}
}
dkp_ 个人密钥。密钥等同本人身份,请勿外传,泄露后在个人中心立即吊销。知识库检索(kb_search)
知识库工具默认在密钥权限范围内自动检索(本人私有 + 组织共享 + 公开库),也可以按名称指定知识库让 AI 精确查找,并内置多轮 + 关联词句增强召回(自动查询扩展 → 多路并行召回 → 关键词精确补充 → 覆盖不足时二轮检索 → 统一重排),无需手工拆分查询:
| 场景 | 用法 |
|---|---|
| 自动检索(默认) | 只传 query,服务端在权限范围内自动选库并增强召回 |
| 按名称指定 | 传 kb_names: ["库名"],支持模糊匹配;未命中时返回可见库名列表便于纠正 |
| 按 id 指定 | 传 kb_ids: [1,2](先用 kb_list 查列表) |
| 追问改写 | 传 history(最近对话),「它呢?」「第二点呢」等指代自动改写成独立问题 |
文件输入约定
外部系统没有服务器路径,标准流程是先用 REST 上传文件换取 file_id,再在 MCP 工具里传 file_id:
sequenceDiagram
participant E as 外部系统
participant R as DJWork REST
participant M as DJWork MCP
E->>R: 1. POST /api/uploads/quick 上传文件(用户 JWT)
R-->>E: 2. 返回 file_id
E->>M: 3. call_tool(传 file_id)
M-->>E: 4. task_id
E->>M: 5. 轮询 *_status / *_get
工具清单
| 模块 | 工具 | 说明 |
|---|---|---|
| 合同审核 | audit_submit / audit_get_detail | 提交审核(file_id 或路径,类型/立场/强度)/ 按 audit_id 查结果 |
| 智能提取 | extract_run / extract_get | 按模板结构化抽取 / 按 result_id 查字段 |
| 文档比对 | compare_run / compare_get | 两份同类型文件差异比对 / 查结果 |
| 印章核验 | seal_verify_start / seal_verify_status | 定位印章页、裁剪章面、识别印章名 / 查进度与逐页结果 |
| NJCA 审核 | njca_audit_submit / njca_audit_status | 批量委托书三要素审核 / 批量查结论与不通过原因 |
| 知识库 / OCR / LLM | kb_* / ocr_* / llm_* | 知识库检索、DianjuOCR v3 代理、OpenAI 兼容补全 |
| 智能脱敏 / 管理 | redact_* / admin_* / usage_* | 脱敏与管理员工具仅管理员可见;usage 为组织用量 |
Python 客户端示例
import asyncio, json, time
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client
DJWORK_URL = "http://<host>:8000/mcp/djwork/"
JWT = "<用户 JWT>" # 组织 Key 经 /api/v1/token 换证获得
async def main():
async with streamablehttp_client(
DJWORK_URL, headers={"Authorization": f"Bearer {JWT}"}
) as (read, write, _):
async with ClientSession(read, write) as session:
await session.initialize()
tools = await session.list_tools()
# 1) REST 上传拿到 file_id 后,提交印章核验
res = await session.call_tool("seal_verify_start", {"file_id": "<file_id>"})
task_id = json.loads(res.content[0].text)["task_id"]
# 2) 轮询结果(扫描件通常 1~5 分钟)
while True:
r = await session.call_tool("seal_verify_status", {"task_id": task_id})
task = json.loads(r.content[0].text)["task"]
if task["status"] in ("completed", "failed", "cancelled"):
print(json.dumps(task, ensure_ascii=False, indent=2))
break
time.sleep(10)
asyncio.run(main())
常见错误
| 现象 | 原因与处理 |
|---|---|
401 unauthorized | JWT 缺失 / 过期,重新换证 |
| 无权调用工具 xxx | 工具对当前角色不可见(如 redact_* 仅管理员) |
| 未获得「xx」的访问权限 | 智能应用未授权,联系管理员在「智能应用管理」开通 |
| 使用次数已用完(x/y) | 应用授权次数耗尽,联系管理员续期 |
限流与配额
为保障多接入方共存时的服务稳定,系统按组织 Key 与用户两个维度做限流与配额控制。接入方应把下述控制项纳入错误处理与重试策略。
控制项一览
| 控制项 | 默认值 | 维度 | 超限表现 |
|---|---|---|---|
| 接口频率 | 60 次 / 分钟(Redis 滑动窗口) | 组织 Key | 429 |
| 用户审核并发 | 管理员按用户配置(1–20) | 用户 | 429 |
| 系统级并发审核总数 | 管理员全局配置 | 全局 | 429 |
| 审核配额 | 按用户剩余次数(quota) | 用户 | 403 |
| 文件大小 | 50MB | 单文件 | 413 |
推荐的重试策略
import time, requests
def call_with_retry(fn, refresh_token, max_retry=4):
for i in range(max_retry):
r = fn()
if r.status_code == 429: # 限流:指数退避
time.sleep(2 ** i)
continue
if r.status_code == 401: # 凭证过期:换证后重试一次
refresh_token()
return fn()
return r
raise RuntimeError("重试次数耗尽")
- 上传前先本地校验大小(≤50MB)与扩展名,避免 413 / 400 无效请求占用限流额度。
- 任务轮询设置总超时(建议审核 ≥10 分钟),超时后仍应以最终轮询到的终态为准。
- 组织聚合用量可通过
GET /api/v1/usage定期拉取,用于你侧的用量看板与预警。
错误处理
所有接口通过 HTTP 状态码 + 统一错误体返回失败原因,语义稳定,建议在你的 SDK / 后端里做一次统一封装。
统一错误码
| 状态码 | 含义 | 典型场景 | 处理建议 |
|---|---|---|---|
400 | 参数错误 | 无效 stance / intensity、文件类型不支持、比对类型不一致 | 修正请求,不要重试 |
401 | 认证失败 | Key / JWT 无效或过期、用户被禁用 | 换发凭证后重试一次 |
403 | 无权限 | Key 模块权限不足、用户冻结、配额不足、组织不允许自动注册 | 按原因提示,不要盲目重试 |
404 | 不存在 | 任务 / 文件 / 模板 / 知识库 / 用户 / 模型不存在 | 核对 ID;任务可能已被删除 |
410 | 已弃用 | POST /api/v1/ticket(一次性票据) | 改用 Token 直跳 |
413 | 文件过大 | 单文件超过 50MB | 本地预检文件大小 |
429 | 限流 | Key 超频、并发达到上限 | 指数退避重试 |
500 | 服务错误 | 内部异常 | 稍后重试;持续失败联系管理员并提供 task_id |
{ "detail": "并发任务数已达上限(3),请等待进行中的任务完成" }
failed 终态并附 error 原因(如文件损坏、格式不支持)——请以轮询终态为准更新业务状态,而不是以提交是否成功为准。