从 curl 到工程封装:文本相似度 API 集成指南
适用场景与背景
文本相似度比对是 NLP 中的基础能力,广泛应用于以下场景:
- 评论/内容审核:检测用户提交的评论是否与已有重复或高度近似
- AI 生成内容检测:将 AI 生成文本与原文比对,辅助判断抄袭或生成痕迹
- 多语言翻译质量评估:翻译后的文本与参考译文计算相似度,量化一致性
- 客服话术匹配:用户提问与标准答案库中的句子做相似度排序,自动返回最佳答案
该接口采用纯本地计算的方式,无外部上游依赖,平均响应 < 100ms,适合对延迟敏感的内部服务、批处理脚本或边缘节点。
接口能力边界
| 维度 | 说明 |
|---|---|
| 请求方法 | POST |
| 端点 | https://v1.apizero.cn/api/text-similarity |
| 单次 QPS | 10 次/秒 |
| 文本长度 | 每段 1~5000 字符(中英文均按 1 字符计) |
| 超长保护 | 超过 500 字符自动截取并按比例还原,5000×5000 字符比对约 60-80ms |
| 鉴权方式 | 可选匿名(每日 100 次)或 API Key(通过X-API-Key或Authorization头,具体以文档为准) |
| 输出指标 | 余弦相似度(权重 35%)、Jaccard 系数(25%)、编辑距离归一化(20%)、LCS 比率(20%) |
| 综合评级 | 5 级:几乎相同、高度相似、中度相似、轻度相似、差异较大 |
注意:接口底层修复了 PHP 内置
levenshtein函数的字节计算 bug,自实现mb_levenshtein支持字符级编辑距离,避免汉字截断问题。
请求参数与鉴权
Header 参数
| 参数 | 是否必填 | 类型 | 说明 | 示例 |
|---|---|---|---|---|
Authorization | 否 | string | API Key 鉴权,格式Bearer sk_live_xxx | Bearer sk_live_xxxxxxxxxxxxxx |
Content-Type | 否 | string | 支持application/json或application/x-www-form-urlencoded | application/json |
鉴权说明:匿名调用时可省略 Authorization 头,每日额度 100 次;建议正式环境使用 API Key 以获取更高配额和稳定性。两种鉴头均可使用,具体以API 文档为准。
请求体(JSON)
| 字段 | 类型 | 必填 | 描述 | 示例 |
|---|---|---|---|---|
text1 | string | 是 | 第一段文本,1~5000 字符 | "今天天气不错,适合出门散步" |
text2 | string | 是 | 第二段文本,1~5000 字符 | "今天天气真好,适合出门走走" |
从 curl 开始:调试与验证
拿到接口后的第一步,通常是用 curl 手动发送请求,确认网络连通和返回结构。以下示例使用环境变量APIZERO_API_KEY存储密钥(匿名时直接去掉对应头即可):
export APIZERO_API_KEY="sk_live_your_key_here" curl -sS \ -X POST \ -H "X-API-Key: $APIZERO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text1": "今天天气不错,适合出门散步", "text2": "今天天气真好,适合出门走走" }' \ "https://v1.apizero.cn/api/text-similarity"响应示例(成功):
{ "code": 0, "msg": "成功", "request_id": "abc123def456", "data": { "text1_length": 13, "text2_length": 13, "truncated": false, "metrics": { "cosine": 0.5833, "jaccard": 0.4118, "edit_distance": 4, "edit_similarity": 0.6923, "lcs_length": 12, "lcs_similarity": 0.9231 }, "overall_score": 0.6471, "similarity_level": "moderately_similar", "level_name": "中度相似" } }通过 curl 我们可以快速确认:接口可通、返回格式符合预期。接下来就需要将这段原始交互封装成工程化代码。
工程封装:Python 与 PHP 示例
Python(requests 库)
import requests import json API_URL = "https://v1.apizero.cn/api/text-similarity" API_KEY = "sk_live_your_key_here" # 匿名调用时设为 None def text_similarity(text1: str, text2: str) -> dict: headers = { "Content-Type": "application/json" } if API_KEY: headers["X-API-Key"] = API_KEY payload = { "text1": text1, "text2": text2 } resp = requests.post(API_URL, headers=headers, json=payload, timeout=5) resp.raise_for_status() return resp.json() # 调用示例 result = text_similarity("今天天气不错,适合出门散步", "今天天气真好,适合出门走走") print(json.dumps(result, ensure_ascii=False, indent=2))PHP(cURL 扩展)
接口后台即为 PHP 实现,用 PHP 调用更为自然:
<?php function textSimilarity(string $text1, string $text2, ?string $apiKey = null): array { $url = 'https://v1.apizero.cn/api/text-similarity'; $payload = json_encode([ 'text1' => $text1, 'text2' => $text2 ], JSON_UNESCAPED_UNICODE); $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => $payload, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'Content-Type: application/json', $apiKey ? 'X-API-Key: ' . $apiKey : '', ], CURLOPT_TIMEOUT => 5, ]); $response = curl_exec($ch); if (curl_errno($ch)) { throw new RuntimeException('cURL Error: ' . curl_error($ch)); } curl_close($ch); return json_decode($response, true); } $result = textSimilarity('今天天气不错,适合出门散步', '今天天气真好,适合出门走走'); print_r($result);返回值详解
成功响应顶层包含code、msg、request_id和data。重点看data对象:
| 字段 | 类型 | 说明 |
|---|---|---|
text1_length | int | 第一段文本实际字符长度(截取前) |
text2_length | int | 第二段文本实际字符长度(截取前) |
truncated | bool | 是否进行了截取(仅当某段 >500 字符才为true) |
metrics.cosine | float | 余弦相似度,取值范围 [0,1],1 表示完全相同 |
metrics.jaccard | float | Jaccard 系数(基于字符集合交并比),范围 [0,1] |
metrics.edit_distance | int | 字符级编辑距离(莱文斯坦距离) |
metrics.edit_similarity | float | 编辑距离归一化后的相似度 = 1 - (edit_distance / max(len)) |
metrics.lcs_length | int | 最长公共子序列(LCS)的长度 |
metrics.lcs_similarity | float | LCS 长度与较长文本长度的比值 |
overall_score | float | 加权综合评分 = 0.35cosine + 0.25jaccard + 0.20edit_similarity + 0.20lcs_similarity |
similarity_level | string | 英文级别标识(nearly_identical,highly_similar,moderately_similar,slightly_similar,different) |
level_name | string | 中文级别名称 |
评级阈值参考(以文档为准)
| 级别 | 综合评分范围(近似) | 含义 |
|---|---|---|
| 几乎相同 | ≥0.95 | 文本高度一致,仅有微小差异 |
| 高度相似 | [0.80,0.95) | 核心内容相似,可能词汇或语序不同 |
| 中度相似 | [0.55,0.80) | 主题相关,但存在一定差异 |
| 轻度相似 | [0.30,0.55) | 仅少部分相同或语义接近 |
| 差异较大 | <0.30 | 文本几乎无关联 |
错误处理与常见问题
错误响应示例
{ "code": 1001, "msg": "参数错误:text1 不能为空", "request_id": "err_req_001", "data": null }| code | 含义 | 排查方向 |
|---|---|---|
| 0 | 成功 | - |
| 1001 | 参数缺失或格式错误 | 检查text1、text2是否必填;确认 JSON 合法性 |
| 1002 | 文本长度超限 | 保证每段 ≤5000 字符(含空格和标点) |
| 2001 | 鉴权失败 | 检查 API Key 是否正确,是否过期;匿名调用是否超过每日 100 次 |
| 5000 | 服务端内部错误 | 联系接口提供方,并附带request_id |
常见问题
- 中文乱码:请确保发送请求时使用 UTF-8 编码。Python 的
requests库默认使用 UTF-8;PHP 用JSON_UNESCAPED_UNICODE选项保证中文不被转义。 - 超长文本:当文本超过 500 字符时接口会自动截取前 500 字符并记录
truncated: true,评分基于截取后的文本计算。如果业务需要精确结果,建议客户端先截取后再请求。 - 匿名调用限制:每日 100 次,超出后返回 2001 错误。生产环境应配置 API Key。
工程化注意事项
1. 重试与退避
网络波动可能造成偶发失败,建议在封装层加入指数退避重试逻辑(最多 3 次,间隔 1s、2s、4s)。注意不要重试 4xx 错误(如参数问题),只重试 5xx 或超时。
2. 结果缓存
如果对同一对(text1, text2)频繁请求,可在应用层使用 LRU 缓存(如 Python 的functools.lru_cache)缓存结果,避免重复网络开销。TTL 可根据业务容忍的数据新鲜度设置。
3. 超时设置
接口平均耗时 <100ms,但极端情况下(如文本长度 5000 字符)可能达到 80ms,建议请求超时设为 2~5 秒,避免因接口挂起阻塞整个服务。
4. 文本预处理
- 去噪:去除首尾空格、HTML 标签、多余换行符等,减少无关字符对相似度的影响。
- 标准化:全角/半角转换,统一大小写(英文场景)。
- 分段:如果文本超过 5000 字符,需在客户端分段后分别对比,或取前 5000 字符。
5. 性能考量
接口 QPS 为 10 次/s,如果需要批量对比大量文本对,应当控制并发量(如使用信号量限制最大 10 个并发请求),或实现批量处理队列,避免触发限流。
参考文档
- 官方接口文档:https://apizero.cn/aidocs/text-similarity
- 原始 Markdown 文档:https://apizero.cn/aidocs/text-similarity/raw.md
本文所有字段解释和示例均以文档为准,调用前请查阅最新文档以获取准确信息。
