Context7 TypeScript SDK 实战:用 searchLibrary 与 getContext 为 LLM 和 RAG 获取版本化文档
本文围绕 Context7 仓库中的 TypeScript SDK(@upstash/context7-sdk)展开,讲清楚它的定位、安装与初始化方式、两个核心方法 searchLibrary 和 getContext 的完整用法,并结合 源码实现 深入解析其请求端点、重试策略、错误处理与类型推导机制。读完本文,你可以在 AI Agent、RAG 流水线或代码生成工具中接入 Context7,让模型基于最新、版本特定的库文档回答问题,而不是依赖过期的训练数据。
一、为什么需要 Context7 SDK
官方 README 指出了 SDK 要解决的问题:LLM 依赖过时或泛化的训练数据来理解你使用的第三方库,这会导致:
- 基于多年前的训练数据生成代码示例;
- 幻觉出不存在的 API;
- 针对旧版包装给出通用但过时的回答。
Context7 通过直接从源头提供"最新的、版本特定的文档与代码示例"来解决该问题。SDK 本身是一个面向 TypeScript 的 HTTP/REST 客户端,构建在 Context7 API 之上,官方文档列出三类典型使用场景:
- 为 AI Agent 提供准确、实时的文档上下文;
- 用可靠的库文档构建 RAG 流水线;
- 为代码生成工具提供真实的 API 参考。
需要注意,SDK 目前处于积极开发阶段(README 开头有 Work in Progress 声明),API 可能随版本引入破坏性变更。当前仓库中 package.json 显示的版本为 0.3.1,MIT 协议。
二、安装与包结构
安装
npm install @upstash/context7-sdk
获取 API Key
API Key 需要从 Context7 平台获取,格式形如 ctx7sk-...。
包的工程结构
从 package.json 可以看到该包的关键工程事实:
| 项目 | 内容 | 说明 |
|---|---|---|
| 包名 | @upstash/context7-sdk |
公开发布(publishConfig.access: public) |
| 模块形态 | "type": "module",同时提供 ESM(dist/client.js)与 CJS(dist/client.cjs)入口 |
现代 ESM 项目与传统 CommonJS 项目均可直接引入 |
| 类型声明 | dist/client.d.ts |
开箱即用的完整 TypeScript 类型 |
| 构建工具 | tsup | pnpm build 触发 |
| 测试框架 | vitest | pnpm test 触发 |
| 运行时依赖 | 无(devDependencies 中仅构建/测试工具链) | 客户端基于标准 fetch 实现 |
三、客户端初始化与配置
基本用法
import { Context7 } from "@upstash/context7-sdk";
const client = new Context7({
apiKey: "<CONTEXT7_API_KEY>",
});
环境变量方式
也可以在环境中配置 API Key,然后以无参方式初始化:
CONTEXT7_API_KEY=ctx7sk-...
const client = new Context7();
初始化行为的源码解析
初始化逻辑集中在 client.ts 构造函数,可以从中读出以下事实:
- Key 的取值优先级:
config.apiKey || process.env.CONTEXT7_API_KEY,即构造函数传入的apiKey优先于环境变量; - 缺失 Key 会直接抛错:两者都取不到时抛出
Context7Error,错误信息为"API key is required. Pass it in the config or set CONTEXT7_API_KEY environment variable."。这一点由 client.test.ts 中的用例 明确验证(同时删除两个环境变量后断言new Context7()抛出含 "API key is required" 的错误); - 前缀校验仅为警告:若 Key 不以
ctx7sk开头,只调用console.warn提示,不阻断初始化; - 鉴权方式:Key 被放入
Authorization: Bearer <key>请求头; - 端点基址固定:
DEFAULT_BASE_URL = "https://context7.com/api"(client.ts#L12)。虽然HttpClient的构造参数支持传入baseUrl,但从源码结构看,Context7公开构造函数并未暴露改写基址的选项,即当前版本只能指向官方 API; - 默认重试与缓存策略:构造函数内置
retry: { retries: 5, backoff: (n) => Math.exp(n) * 50 }与cache: "no-store",保证请求不被本地缓存、失败时自动指数退避重试。
当前版本 Context7Config 接口只包含可选的 apiKey 字段,配置面非常小——这是 WIP 阶段的现状。
四、searchLibrary:按问题检索目标库
完整示例
// 搜索库(默认返回 Library[] 数组)
const libraries = await client.searchLibrary(
"I need to build a UI with components",
"react"
);
console.log(libraries[0].id); // "/facebook/react"
参数与方法签名
searchLibrary 发起 GET 请求到 v2/libs/search 端点,携带 query 与 libraryName 两个查询参数(见 search-library/index.ts):
| 参数 | 类型 | 说明 |
|---|---|---|
query |
string,必填 |
用户的问题或任务描述,用于相关性排序 |
libraryName |
string,必填 |
要搜索的库名 |
options.type |
"json" | "txt",默认 "json" |
响应格式:JSON 数组或格式化纯文本 |
query 或 libraryName 为空时会抛出 Context7Error("query and libraryName are required"),client.test.ts#L154-L156 验证了这一行为。
Library 返回结构
每个结果被 formatLibrary 归一化为 Library 对象,字段定义见 commands/types.ts:
| 字段 | 类型 | 说明 |
|---|---|---|
id |
string |
Context7 库 ID,如 /react/react,是后续 getContext 的入参 |
name |
string |
库的展示名(对应 API 返回的 title) |
description |
string |
库描述 |
totalSnippets |
number |
可用文档片段数,缺失时默认 0 |
trustScore |
number |
来源信誉分(0-10),缺失时默认 0 |
benchmarkScore |
number |
质量指标分(0-100),缺失时默认 0 |
versions |
string[] |
可用版本/标签(可选) |
txt 模式的文本渲染规则
指定 { type: "txt" } 时,SDK 会调用 formatLibrariesAsText 生成人类(或 LLM)可直接阅读的文本块,各库之间以 ---------- 分隔;若无结果则返回 "No documentation libraries found matching your query."。其中 trustScore 会被映射为可读标签,映射规则见 getTrustScoreLabel:
| trustScore 取值 | 标签 |
|---|---|
| ≥ 7 | High |
| 4 – 6.9 | Medium |
| < 4 | Low |
| 缺失或负值 | Unknown |
totalSnippets 为 0 时不输出 Code Snippets 行,benchmarkScore 为 0 时不输出该行,versions 非空时以逗号拼接输出。
五、getContext:获取文档上下文
完整示例
// 默认:JSON 数组形式
const docs = await client.getContext("How do I use hooks?", "/facebook/react");
console.log(docs[0].title, docs[0].content);
// 纯文本形式
const context = await client.getContext(
"How do I use hooks?",
"/facebook/react",
{ type: "txt"
});
console.log(context);
请求参数
getContext 发起 GET 请求到 v2/context 端点(见 get-context/index.ts),查询参数如下:
| 参数 | 必填 | 说明 |
|---|---|---|
query |
是 | 用户问题或任务 |
libraryId |
是 | Context7 库 ID,如 /react/react |
type |
否 | "json"(默认)或 "txt",会作为查询参数发给服务端 |
json 模式:Documentation[] 的组装过程
json 模式下,服务端返回 { codeSnippets, infoSnippets } 两类原始片段(结构见 get-context/types.ts),SDK 将其统一映射为 Documentation[]:
interface Documentation {
title: string; // 片段标题
content: string; // 内容,可能包含 Markdown 代码块
source: string; // 来源 URL 或标识
}
组装逻辑在 get-context/index.ts#L43-L47:先把 codeSnippets 逐个经 formatCodeSnippet 转换,再把 infoSnippets 逐个经 formatInfoSnippet 转换,最后 codeDocs 在前、infoDocs 在后拼接返回。两个格式化函数的具体规则:
- 代码片段:
title取codeTitle;content为codeDescription(若有)加空行后接若干用\``围栏包裹的代码块(多段代码以空行分隔);source取codeId`; - 信息片段:
title取breadcrumb,缺失时回退为"Documentation";content直接透传;source取pageId。
这意味着 json 模式的输出可以无损地灌入 LLM 上下文:每个片段自带标题、可渲染的内容与溯源标识,适合做 RAG 的 chunk 级引用。
txt 模式:纯文本与分页元信息
txt 模式直接把服务端的文本响应原样返回为 string(get-context/index.ts#L39-L41)。值得注意的是,HTTP 层还会解析 txt 响应头中的分页元数据(见 HttpClient.extractTxtResponseHeaders):
| 响应头 | 字段 | 含义 |
|---|---|---|
x-context7-page |
page |
当前页 |
x-context7-limit |
limit |
每页数量 |
x-context7-total-pages |
totalPages |
总页数 |
x-context7-has-next / x-context7-has-prev |
hasNext / hasPrev |
是否有下一页/上一页 |
x-context7-total-tokens |
totalTokens |
总 token 数 |
这些元信息用于判断文档是否被分页截断、估算上下文占用,方便调用方决定是否需要翻页拉取完整文档。
六、HTTP 层:重试、退避与错误处理
SDK 的所有请求都经由 HttpClient 发出,值得了解的实现细节:
- 重试循环:
request内部以for (let i = 0; i <= this.retry.attempts; i++)循环调用fetch,网络层异常时按backoff(i)等待后重试,等待时间按Math.exp(i) * 50毫秒递增(约 50ms、136ms、369ms、1002ms、2716ms);若请求被主动AbortSignal中止则立即抛出,不做无谓重试(http/index.ts#L153-L169); - HTTP 错误映射:非 2xx 响应会尝试解析响应体中的
error或message字段,最终统一抛出Context7Error(定义见 error/index.ts),调用方只需捕获这一个错误类型; - 响应解析:按
Content-Type区分application/json(解析为 JSON)与文本(原样返回并附带上述分页头); - 请求细节:统一携带
Content-Type: application/json与Authorization: Bearer头,keepalive: true,缓存策略no-store,确保每次获取的都是服务端最新文档。
测试侧同样覆盖了失败路径:对不存在的库 ID 调用 getContext 会 reject 抛错(client.test.ts#L150-L152)。
七、类型推导:重载签名保证返回类型精确
searchLibrary 与 getContext 在 client.ts#L47-L131 中使用了三重重载签名,TypeScript 编译器可根据第三参推导精确的返回类型:
| 调用形式 | 返回类型 |
|---|---|
client.searchLibrary(q, lib) 或 { type: "json" } |
Promise<Library[]> |
{ type: "txt" } |
Promise<string> |
client.getContext(q, id) 或 { type: "json" } |
Promise<Documentation[]> |
{ type: "txt" } |
Promise<string> |
client.test.ts 的 "type inference" 分组 专门验证了这两种返回形态,保证"不传 type 得到数组、传 txt 得到字符串"这一契约在运行期同样成立。测试整体覆盖了构造器(含环境变量回退与缺 Key 抛错)、searchLibrary 多查询检索、getContext 的 json/txt 两种格式、多库(Vue、Express)场景与错误处理。
八、开发与验证
在仓库根目录下针对 packages/sdk 子包,README 给出两条验证命令:
pnpm test # 运行 vitest 测试套件
pnpm build # 使用 tsup 构建产物到 dist/
其中测试依赖真实 API Key:client.test.ts#L6 从 CONTEXT7_API_KEY(或 API_KEY)环境变量读取,集成类用例需要有效 Key 才能跑通。
九、参考文件清单
如需进一步深入,可按以下路径继续阅读当前仓库(路径均相对仓库根目录):
| 文件 | 内容 |
|---|---|
| packages/sdk/README.md | SDK 官方说明(本文主体文档) |
| packages/sdk/package.json | 包元信息、构建与测试脚本 |
| packages/sdk/src/client.ts | Context7 客户端主类、端点基址与鉴权 |
| packages/sdk/src/commands/types.ts | Context7Config、Library、Documentation 等公共类型 |
| packages/sdk/src/commands/search-library/index.ts | 库搜索命令与 v2/libs/search 端点 |
| packages/sdk/src/commands/get-context/index.ts | 文档上下文命令与 v2/context 端点 |
| packages/sdk/src/http/index.ts | HttpClient:重试、退避、分页响应头解析 |
| packages/sdk/src/error/index.ts | Context7Error 统一错误类型 |
| packages/sdk/src/utils/format.ts | 片段/库的格式化与 trustScore 标签映射 |
| packages/sdk/src/client.test.ts | 客户端行为与类型契约的集成测试 |
此外,仓库 docs/sdks/ts/ 目录下还有面向终端用户的配套文档(getting-started、search-library、get-context),可作为本文的补充阅读材料。
小结
@upstash/context7-sdk 是一个面积极小但职责清晰的客户端:两个方法(searchLibrary 定位库、getContext 取文档)、一种鉴权方式(ctx7sk- 前缀的 API Key)、一套可靠的传输保障(指数退避重试 + 统一错误类型 + 分页元信息)。对于要构建文档驱动型 AI 应用的 TypeScript 项目,"searchLibrary 拿到库 ID → getContext 拿到 Documentation[] → 注入 LLM 上下文"就是完整的接入链路;当前 0.3.x 版本仍标注 WIP,升级时建议留意破坏性变更说明。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00