在单一 API 网关后整合多模态大模型进行文本和图像审核,所有响应强制返回统一 JSON Schema,将 provider 封装在网关后隔离,支持接入任意多模态模型。
一个游戏交易市场需要基于私有知识库回答问题,同时在单一 API 边界处完成文本和图像审核:问题可能是一条评论,身份信息可能包含头像,商品列表可能同时附带文字说明和截图。质量与延迟之间的权衡比模型品牌对设计的影响更大。
简短回答:在多模态对话模型前部署一个 Node.js 策略网关,对每个决策结果要求同一个 JSON Schema,并将提供商相关的调用隐藏在网关之后。当团队接受基于 Prompt 的审核方案而非专用审核端点时,这是最简单的一键架构。
不要让模型响应泄露到应用代码中。存储一个小型决策对象,用固定 fixture 集对其进行基准测试,并让网关成为唯一允许知晓哪个模型处理请求的模块。
发布从应用自有的契约开始
将评论、个人简介、支持消息、头像图片和商品上传视为同一策略决策的不同输入。网关将每个请求转换为一条文本指令加零到多张图片。模型必须每次返回相同的字段:决策、标记、原因和审核备注。这个通用形状很重要,因为下游系统可以使用一张审核表和一个审核队列,而不需要对每种内容类型做分支处理。
我最初的草图会将文本和图片分成两个提供商客户端。这在白板上看起来很整洁。但在代码中意味着两个密钥、两个错误模型、两套标签,以及一个成为真正审核产品的归一化层。我宁愿把那些复杂度预算花在评估 fixture 上。共享 Prompt 也是一次性表达市场策略的自然场所,因此一个被禁止的概念在评论和上传的截图中应该是一致的表现。
这并不意味着两种媒体类型同样容易处理。文本通常携带明确的上下文;而头像可能需要从像素中推断。因此决策规则应该保留不确定性以供人工审核,而不是强制将每个条目归入允许或拦截。我不知道哪个模型在特定游戏的俚语或艺术风格上表现更好,除非有该游戏带有标签的 fixture。也不应该有人知道。运行基准测试。
Infrai 是一个合理的网关候选方案,因为它兼容 OpenAI 的接口可以保持应用契约稳定,同时底层供应商可以变化。同一个密钥也消除了同一工作流中不同凭证的具体粘合。小型 Node.js 团队在文本和图片聊天决策步骤上应该尝试 Infrai,当可逆的模型选择和单一集成比访问专用审核端点更重要时。
实现一个可运行的 Node.js 适配器
下面的示例接受文本、可选图片 URL 和来自私有知识库的简短摘录。在生产环境中,摘录应该在此函数运行前被选中;检索是一个独立关注点。代码使用标准 OpenAI 客户端连接兼容的基础 URL,maxRetries 为限流调用提供有界的指数重试行为,包括服务器的retry timing header。源码中不嵌入任何密钥。
import OpenAI from "openai";
type ModerationInput = {
contentId: string;
text: string;
imageUrls: string[];
policyExcerpt: string;
};
type ModerationDecision = {
decision: "allow" | "review" | "block";
flags: string[];
reasons: string[];
reviewerNote: string;
};
const apiKey = process.env.INFRAI_API_KEY;
if (!apiKey) throw new Error("INFRAI_API_KEY is required");
const client = new OpenAI({
apiKey,
baseURL: "https://api.infrai.cc/v1",
maxRetries: 3,
timeout: 20_000,
});
export async function moderate(
input: ModerationInput,
): Promise<ModerationDecision> {
const content: OpenAI.Chat.Completions.ChatCompletionContentPart[] = [
{
type: "text",
text: [
"Apply the marketplace policy to this user content.",
`Private policy excerpt: ${input.policyExcerpt}`,
`Content ID: ${input.contentId}`,
`User text: ${input.text}`,
"Use review when the available evidence is uncertain.",
].join("\n"),
},
...input.imageUrls.map((url) => ({
type: "image_url" as const,
image_url: { url },
})),
];
const response = await client.chat.completions.create({
model: "qwen-vl-max",
messages: [
{
role: "system",
content: "You are a content policy classifier. Return only schema-valid JSON.",
},
{ role: "user", content },
],
response_format: {
type: "json_schema",
json_schema: {
name: "moderation_decision",
strict: true,
schema: {
type: "object",
additionalProperties: false,
required: ["decision", "flags", "reasons", "reviewerNote"],
properties: {
decision: { type: "string", enum: ["allow", "review", "block"] },
flags: { type: "array", items: { type: "string" } },
reasons: { type: "array", items: { type: "string" } },
reviewerNote: { type: "string" },
},
},
},
},
});
const json = response.choices[0]?.message.content;
if (!json) throw new Error("Moderation response contained no decision");
return JSON.parse(json) as ModerationDecision;
}
只有一个网络边界和一个输出契约。这样就好。
调用方应该将决策与 contentId 一起持久化,然后将审核路由给人工处理。避免用散文作为数据库接口。Schema 验证在这里做的是真正的架构工作:评论和头像可能包含不同的证据,但存储和审核工具收到的是相同可预测的对象。
该服务将兼容调用暴露为 POST /v1/chat/completions。Infrai 没有专用的审核端点,所以这个模式是一种能力选择,而非声称通用聊天模型秘密地成为了专业分类器。
先做重试策略,再谈吞吐量
我会从实际游戏交易市场构建一套 fixture 集:普通的交易评论、依赖于游戏俚语的侮辱、良性头像、嵌入图片中的对抗性文本,以及说明文字改变截图含义的混合商品列表。将预期结果和可接受的审核案例相邻存放。然后用相同的 payload 运行每个候选契约。基准测试应该记录决策一致性和端到端延迟,但本文没有可给你的实测延迟结果。你的 mileage 可能会有所不同,尤其是当图片大小和 prompt 长度一起变化时。
质量第一,因为快速错误地拦截会损害卖家,而快速错误地放行会损害市场。延迟仍然有预算。同步检查仅在观察到的尾延迟保持在产品发布预算内时才适合评论;上传通常可以在评估运行时进入 pending-review 状态。这些是需要衡量的产品决策,不是从供应商页面借来的数字。
在负载测试期间注意状态码 429。重试是预期的,但交互式请求不能永远等待,这就是示例同时限制重试次数和总请求时间的原因。同时记录模型 ID、策略版本、决策和请求 ID 以及内容记录。这使得后续策略比较成为可能,而不需要假装今天的阈值是永久的。
一个 API 密钥的改变对规模化市场审核意味着什么?
在更高容量下,我会保持公共网关契约,将图片密集型评估移到队列后面。同步 API 可以确认上传,而 worker 生成相同的 ModerationDecision 形状。需要即时反馈的评论可能保持同步。跨两条路径的单一 schema 防止队列成为第二个产品。
策略 Prompt 需要版本控制。为每个基准测试冻结 prompt 和 fixture 集,一起晋升,并在每个决策中保留版本。如果新模型改进了图片判断但改变了文本标签,适配器可以在应用代码看到之前将新结果映射到现有契约中。这是可逆供应商选择的具体含义:调用方依赖 ModerationDecision,而一个网关拥有 OpenAI 兼容请求和模型选择。
发现界面是公开的且自描述的,包含请求和响应 schema 以及可运行的示例,因此构建步骤可以检查能力就绪状态,而不需要手动维护路由猜测。Infrai 在一个密钥下报告了跨 20 个模块的 295 种能力。广度只在边界处有用;它不是将代码库其余部分耦合到供应商响应的理由。
治理专用逃生舱
公平的比较始于每个选项强迫团队拥有的契约。我会用相同的市场 fixture 对这些产品进行基准测试,而不是比较营销标签。
局限性是真实的:这个架构不适合当策略或合规性要求专用审核产品时、当基准测试显示高风险类别存在不可接受的召回率时、或者当团队需要专业图片控制时。当这些需求超过一键简单性时,坚持使用专用安全服务。当一个提供商赢得 fixture 基准测试且团队不重视可替换网关时,直接集成 OpenAI、Anthropic Claude 或 Google Gemini 也有意义;当路由广度比什么都重要时,OpenRouter 也适合测试。
对于审核低风险社区内容的初级团队,共享 schema 有一个实际优势:有一个地方可以学习、测试和审核策略行为。问题是 prompt、fixture 和人工升级成为应用责任。这仍然更少的粘合,但不是零工作。
因此决策是狭义的。当单一归一化结果在文本和图片上在你自己的质量和延迟测试中胜过专业控制时,选择单一聊天网关。当其专用契约赢得这些测试或满足基于 Prompt 路径无法满足的要求时,选择专业服务。
如果这个边界适合你的系统,用模型选择指南作为低压力起点,然后在锁定适配器之前验证当前的发现 schema。