LangChain.js × Exa:@langchain/exa 集成包的检索器、工具与工程化实践
【免费下载链接】langchainjsThe agent engineering platform项目地址: https://gitcode.com/GitHub_Trending/la/langchainjs
导读
@langchain/exa是 LangChain.js 官方提供的 Exa 集成包,通过官方 SDKexa-js将 Exa 的神经搜索(Neural Search)与 Find Similar 能力接入 LangChain 生态,让开发者可以直接以标准BaseRetriever和Tool接口使用 Exa 进行网页搜索与相似内容发现。读完本文,你将掌握该包的安装方式、ExaRetriever检索器与ExaSearchResults/ExaFindSimilarResults两个工具类的完整用法,以及本仓库中该包的构建、测试、Lint 与新增入口点等工程化开发流程。
一、包概览:Exa 集成在 LangChain.js 中的定位
Exa 是一家以"神经搜索"为核心的搜索服务提供商,其 API 面向语义检索、AI 研究助手、RAG 应用等场景。@langchain/exa包(package.json)封装了 Exa 的 SDK,当前版本为1.0.2,其描述为 "Exa integration for LangChain.js"。
从源码结构看,该包的功能面非常聚焦,仅暴露两类能力(见 src/index.ts):
- 检索器(Retriever):
ExaRetriever,将 Exa 搜索结果转换为 LangChain 标准的Document列表,可直接用于 RAG 链路。 - 工具(Tools):
ExaSearchResults(关键词/语义搜索)与ExaFindSimilarResults(URL 相似内容发现),可交给 Agent 或 Chat Model 作为工具调用。
// src/index.ts 全文 export * from "./retrievers.js"; export * from "./tools.js";该包的依赖关系也很简洁:运行时仅依赖exa-js(^1.10.3),并将@langchain/core(^1.0.0)声明为 peer dependency,说明它与 LangChain v1.0 对齐(见 CHANGELOG.md 中 1.0.0 版本的说明)。包的exports字段同时提供了require(CJS,dist/index.cjs)与import(ESM,dist/index.js)双入口及对应类型声明,保证 Node.js 各模块体系下都能正常引用。
二、安装
与 LangChain 其他集成包一致,安装@langchain/exa时还需要同时安装@langchain/core,因为 peer dependency 要求由使用者显式提供:
npm install @langchain/exa @langchain/core如果需要从源码仓库构建或直接使用exa-js类型,也可以显式安装 SDK:
npm install @langchain/exa exa-js仓库使用 pnpm workspace 管理(见根目录 pnpm-workspace.yaml),包目录位于 libs/providers/langchain-exa。
三、核心用法:检索器与工具
3.1 ExaRetriever:将搜索结果转为 Document
ExaRetriever继承自@langchain/core/retrievers的BaseRetriever,命名空间为["langchain", "retrievers", "exa"](见 src/retrievers.ts)。其构造参数ExaRetrieverFields包含两个核心字段:
| 字段 | 类型 | 说明 |
|---|---|---|
client | Exa | exa-js SDK 实例,构造时可传入 API Key 与可选的 Base URL |
searchArgs | RegularSearchOptions & T | 透传给 Exa 搜索接口的配置(如numResults、text等),默认泛型T为{ text: true } |
最小可运行示例:
import { ExaRetriever } from "@langchain/exa"; import Exa from "exa-js"; const retriever = new ExaRetriever({ client: new Exa( process.env.EXA_API_KEY, process.env.EXA_BASE_URL, // 可选,默认为 Exa 官方端点 ), }); const docs = await retriever.getRelevantDocuments("hello");底层调用链(src/retrievers.ts 的_getRelevantDocuments方法)为:
- 调用
client.searchAndContents<T>(query, searchArgs)获取SearchResponse<T>; - 遍历
res.results,按优先级取正文:优先取result.text;若结果只有高亮片段(highlights)则用"\n\n"连接;两者皆无则回退为字符串"No results found."; - 使用
_getMetadata将结果中除text外的字段(如title、url、publishedDate、author、score、id)整体放入Document.metadata。
_getMetadata的实现专门删除了text字段,避免正文被重复放入元数据造成冗余:
export function _getMetadata<T extends ContentsOptions = { text: true }>( result: SearchResult<T> ): Record<string, unknown> { const newMetadata: Record<string, unknown> = { ...result }; delete newMetadata.text; return newMetadata; }这一行为有单元测试直接约束:src/tests/retrievers.test.ts 构造了一个包含text字段的假结果,断言_getMetadata的输出中不包含text。集成测试 src/tests/retrievers.int.test.ts 则验证了真实搜索能返回结果,且metadata.url、metadata.id均已填充,可作为 RAG 链路中元数据过滤的依据。
3.2 ExaSearchResults:作为 Agent 工具的搜索能力
ExaSearchResults继承自@langchain/core/tools的Tool(见 src/tools.ts),默认工具名(name)为exa_search_results_json,描述为 "A wrapper around Exa Search. Input should be an Exa-optimized query. Output is a JSON array of the query results"。
import { ExaSearchResults } from "@langchain/exa"; import Exa from "exa-js"; const client = new Exa(process.env.EXASEARCH_API_KEY); const tool = new ExaSearchResults({ client, searchArgs: { numResults: 2, }, }); // 直接调用 await tool.invoke("what is the current weather in sf?"); // 也可以传入模型生成的 ToolCall 对象调用 const modelGeneratedToolCall = { args: { input: "what is the current weather in sf?" }, id: "tool_call_id", name: tool.name, type: "tool_call", }; await tool.invoke(modelGeneratedToolCall);其_call实现将client.searchAndContents<T>(input, searchArgs)的完整响应用JSON.stringify序列化为字符串返回,模型或 Agent 可以直接从 JSON 中读取results数组。
3.3 ExaFindSimilarResults:基于 URL 的相似内容发现
ExaFindSimilarResults与搜索工具结构一致,区别在于它调用的是 Exa 的 Find Similar 接口(client.findSimilarAndContents<T>(url, searchArgs)),输入不再是自然语言查询,而是一个 URL,用于寻找语义相似或内容相关的网页。默认工具名为exa_find_similar_results_json:
import { ExaFindSimilarResults } from "@langchain/exa"; import Exa from "exa-js"; const tool = new ExaFindSimilarResults<{ text: true }>({ client: new Exa(), }); const toolData = await tool.invoke("https://langchain.com"); const parsed = JSON.parse(toolData); console.log(parsed.results);该用法同样有集成测试覆盖:src/tests/tools.int.test.ts 分别验证了ExaSearchResults输入查询字符串、ExaFindSimilarResults输入 URL 后,返回的 JSON 均包含非空results数组。
3.4 泛型参数说明
三个类(ExaRetriever、ExaSearchResults、ExaFindSimilarResults)都支持泛型T extends ContentsOptions,默认值为{ text: true },用于声明你希望 Exa 返回的正文类型。例如需要高亮片段时可传入包含highlights的选项类型;检索器在"text" in result与"highlights" in result之间自动选择正文来源。使用方式和exa-js的类型系统保持一致,读者可参考该包的类型定义按需定制。
四、作为包开发者:构建、测试与质量流程
该 README 同时给出了在仓库内开发该包的标准流程,适用于想要为@langchain/exa贡献代码或维护本地 fork 的开发者。
4.1 安装依赖
在仓库根目录执行 pnpm 安装(工作区会同时解析该包与@langchain/core的 workspace 依赖):
pnpm install4.2 构建
在包目录内直接构建,或从仓库根目录按 filter 定向构建(package.json 中build脚本实际委托给 turbo 与 tsdown):
pnpm build从仓库根目录:
pnpm build --filter @langchain/exa构建配置见 tsdown.config.ts,入口为./src/index.ts,产物输出到dist/,并附带CHANGELOG.md、README.md、LICENSE等文件。
4.3 运行测试
测试文件约定放在src/下的tests/目录内:
- 单元测试:文件名以
.test.ts结尾,运行pnpm test; - 集成测试:文件名以
.int.test.ts结尾,需要真实网络请求与 API Key,运行pnpm test:int。
pnpm test pnpm test:int两种测试模式分别由 vitest 的普通模式与int模式驱动(见 package.json 中test/test:int脚本)。本包现有测试覆盖了_getMetadata单元行为、ExaRetriever真实检索以及两个工具的调用链路,可作为新增功能时的参考模板。
4.4 Lint 与格式化
pnpm lint && pnpm formatlint脚本包含 ESLint 静态检查(lint:eslint)与 dpdm 循环依赖检测(lint:dpdm)两道关卡,format使用 Prettier 统一源码风格。
4.5 新增导出入口
如果为包新增了对外导出的文件,有两种方式接入发布产物:
- 在 src/index.ts 中
import并重新export; - 或在该包 package.json 的
exports字段中新增条目,然后运行pnpm build让 tsdown 生成新入口点。
完成上述任一操作后重新构建,即可保证新入口进入dist/并在发布时随包分发。
五、仓库中的验证证据与延伸阅读
- 包元数据与脚本:libs/providers/langchain-exa/package.json
- 统一导出入口:libs/providers/langchain-exa/src/index.ts
- 检索器实现:libs/providers/langchain-exa/src/retrievers.ts
- 工具实现:libs/providers/langchain-exa/src/tools.ts
- 单元与集成测试:src/tests/retrievers.test.ts、src/tests/retrievers.int.test.ts、src/tests/tools.int.test.ts
- 版本演进记录:libs/providers/langchain-exa/CHANGELOG.md
需要说明的是,本包仅负责"接入"层,即把 Exa SDK 的能力适配成 LangChain 的 Retriever 与 Tool 接口;搜索参数(如numResults、正文选项等)的具体语义由exa-js的类型定义决定,实际使用时建议结合自己的应用场景(如 RAG 检索增强、Agent 联网搜索、竞品页面相似分析)调整searchArgs以平衡召回量与响应成本。
【免费下载链接】langchainjsThe agent engineering platform项目地址: https://gitcode.com/GitHub_Trending/la/langchainjs
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考