搜索与阅读
/v1/search、/v1/reader、/v1/ocr —— 给模型补上实时信息与文档内容。
三个接口的分工#
模型的知识停在训练截止那天,也读不了你手上的 PDF。这三个接口是补这两个洞的:搜索找到网页,阅读器把网页变成干净正文,OCR 把文档变成文字。它们的产物都是纯文本,直接拼进对话的 messages 即可。
搜索#
检索式进去,一批结果出来。多家上游并发查询后合并去重,你不需要关心命中的是哪家。
curl:限定语言与时效
bash
curl https://ai.oceango.hk/v1/search \ -H "Authorization: Bearer $AIROUTER_SERP_KEY" \ -H "Content-Type: application/json" \ -d '{ "query": "香港 2026 年最低工资", "count": 5, "language": "zh-CN", "freshness": "month" }'querystring必填- 检索式。
countinteger- 返回条数,默认 10。
languagestring- 语言偏好,如
zh-CN、en。 regionstring- 地区偏好,影响结果的本地化程度。
freshnessstringday、week或month,留空表示不限。查时效性强的话题(价格、政策、赛事)时务必带上,否则很容易召回三年前的页面。
响应:rank 是名次,从 1 开始
json
{ "query": "香港 2026 年最低工资", "results": [ { "title": "法定最低工资 - 劳工处", "url": "https://www.labour.gov.hk/...", "snippet": "自 2026 年 5 月 1 日起,法定最低工资水平调整为每小时 ...", "publish_time": "2026-01-15", "rank": 1 } ]}摘要不等于正文
snippet 是搜索引擎给的一两句话,通常不足以回答问题。真要内容,拿 url 再调一次阅读器。网页阅读#
给一个地址,拿回这个页面的正文——去掉导航、广告、页脚这些噪音。直接把原始 HTML 喂给模型是很贵的做法:一个普通新闻页有八成 token 是标签和脚本。
curl:默认输出 Markdown
bash
curl https://ai.oceango.hk/v1/reader \ -H "Authorization: Bearer $AIROUTER_SERP_KEY" \ -H "Content-Type: application/json" \ -d '{ "url": "https://example.com/article/123", "format": "markdown" }'urlstring必填- 要抓取的网页地址。
formatstringmarkdown(默认)、text或html。喂给模型建议用markdown:标题层级和列表结构能保住,模型据此判断段落关系。with_imagesboolean- 为真时在正文里保留图片引用。
响应:cached 会告诉你这次是不是走了缓存
json
{ "url": "https://example.com/article/123", "title": "示例文章标题", "content": "## 小标题\n\n正文段落 ...", "excerpt": "正文开头的一小段,便于快速判断抓对了没有", "words": 1842, "cached": false}命中缓存照样计一次配额
cached 为真表示这次没打上游、返回很快,但它仍然计一次调用。我们把这个字段放进响应体就是为了让你能自己核对账单,而不是等到月底对不上再来问。文档识别#
把 PDF、扫描件、图片里的文字提出来。给地址或者直接给 Base64 都行,两者选一。
curl:识别一个远程 PDF
bash
curl https://ai.oceango.hk/v1/ocr \ -H "Authorization: Bearer $AIROUTER_SERP_KEY" \ -H "Content-Type: application/json" \ -d '{ "url": "https://example.com/contract.pdf", "format": "markdown" }'Python:本地文件走 Base64
python
import base64, os, requests
with open("contract.pdf", "rb") as f: payload = base64.b64encode(f.read()).decode()
r = requests.post( "https://ai.oceango.hk/v1/ocr", headers={"Authorization": f"Bearer {os.environ['AIROUTER_SERP_KEY']}"}, json={"base64": payload, "format": "markdown"}, timeout=180, # 几十页的文档在上游要跑十几秒到几分钟)r.raise_for_status()doc = r.json()print(f"{doc['pages']} 页,{doc['words']} 字")print(doc["content"][:500])urlstring- 文档地址。与
base64二选一。 base64string- 文档内容的 Base64 编码。与
url二选一。 formatstringmarkdown(默认)或text。
OCR 明显比另外两个慢:上游按页处理,几十页跑十几秒是常态。客户端超时给到 180 秒以上,别用默认的 30 秒。
串成一条链#
三个接口最常见的组合是"搜索到网页、读出正文、交给模型总结"。
Python:把实时信息接进对话
python
import os, requests
SERP = {"Authorization": f"Bearer {os.environ['AIROUTER_SERP_KEY']}"}API = "https://ai.oceango.hk/v1"
# 1. 搜索hits = requests.post( API + "/search", headers=SERP, json={"query": "香港 2026 年最低工资", "count": 3, "freshness": "month"}, timeout=30,).json()["results"]
# 2. 逐条读出正文(snippet 太短,不足以回答问题)pages = []for hit in hits: page = requests.post( API + "/reader", headers=SERP, json={"url": hit["url"], "format": "markdown"}, timeout=60, ).json() pages.append(f"来源:{hit['url']}\n\n{page['content'][:2000]}")
# 3. 交给模型,注意这一步换回 sk-ar- 密钥answer = requests.post( API + "/chat/completions", headers={"Authorization": f"Bearer {os.environ['AIROUTER_API_KEY']}"}, json={ "model": "openai/gpt-5.2", "messages": [ {"role": "system", "content": "只依据给定资料回答,并注明来源链接。"}, {"role": "user", "content": "\n\n---\n\n".join(pages) + "\n\n问题:2026 年最低工资是多少?"}, ], }, timeout=120,).json()
print(answer["choices"][0]["message"]["content"])记得截断
示例里对每页正文取了前 2000 字。不截断的话,三个长页面就能撑爆上下文窗口,而超窗的报错发生在计费之后。