在 LangChain.js 中使用 Ollama:@langchain/ollama 集成包完整实战指南
【免费下载链接】langchainjsThe agent engineering platform项目地址: https://gitcode.com/GitHub_Trending/la/langchainjs
导读
@langchain/ollama是 LangChain.js 官方提供的 Ollama 集成包,基于官方ollamaTypeScript SDK 构建,让开发者可以在本地直接运行并调用 Llama、Mistral、Qwen 等开源模型,无需任何云端 API Key。本文从安装与环境准备出发,完整讲解ChatOllama聊天模型、Ollama文本补全模型与OllamaEmbeddings嵌入模型三大核心类的配置参数、工具调用与结构化输出用法,并深入对应源码说明其底层调用链与消息转换机制,最后给出该包自身的本地开发与测试流程。
一、包定位与整体结构
@langchain/ollama位于仓库的 libs/providers/langchain-ollama 目录,其核心代码集中在src/下,从源码结构看共暴露四大类 API:
- ChatOllama:对话模型集成(
BaseChatModel子类),推荐首选; - Ollama:传统文本补全(
LLM子类); - OllamaEmbeddings:嵌入向量生成(
Embeddings子类); - 消息转换工具(utils.ts)与类型定义(types.ts)。
所有导出统一从 src/index.ts 汇总。当前包版本为 1.3.0,要求 Node.js >= 20,运行时依赖ollamaSDK(^0.6.3),并以@langchain/core(^1.0.0)作为 peer dependency,具体可见 package.json。
二、安装与环境准备
1. 安装依赖包
在项目中使用时,需要同时安装集成包与核心包:
npm install @langchain/ollama @langchain/core2. 本地运行 Ollama 服务
本包的一切能力都建立在本地 Ollama 服务之上,需要按以下步骤准备:
- 从 Ollama 官网下载并安装 Ollama(安装包默认自带服务端与 CLI);
- 拉取要使用的模型,例如
ollama pull llama3; - 确认 Ollama 服务已启动(安装完成后一般会自动在后台运行)。
默认情况下,包会连接http://localhost:11434。如果服务运行在非默认地址,可以在实例化模型时通过baseUrl选项自定义。
3. baseUrl 的解析优先级
从 chat_models.ts 的构造函数源码可以确认其优先级规则:
fields.baseUrl > 环境变量 OLLAMA_BASE_URL > 默认值 http://127.0.0.1:11434也就是说,除了在代码中传入baseUrl,也可以直接设置环境变量(例如.env文件或命令行导出):
export OLLAMA_BASE_URL="http://127.0.0.1:11434"在Ollama与OllamaEmbeddings中同样遵循该优先级(见 llms.ts 与 embeddings.ts)。另外注意:Ollama类会对以/结尾的baseUrl做去尾斜杠处理,避免拼接出错。
三、Chat Models:ChatOllama 快速上手
1. 最小示例
import { ChatOllama } from "@langchain/ollama"; const model = new ChatOllama({ model: "llama3", // 默认值。 }); const result = await model.invoke(["human", "Hello, how are you?"]);其中model的默认值就是"llama3"。invoke的入参既可以是字符串,也可以是一组 LangChain 消息对象(如HumanMessage、SystemMessage等)。返回结果是标准AIMessage,包含content、response_metadata、usage_metadata等字段。
2. 构造函数支持的两种写法
从 chat_models.test.ts 的单元测试可以确认,ChatOllama构造函数支持两种等价形式:
// 形式一:直接传模型名字符串 const modelFromString = new ChatOllama("llama3"); // 形式二:传完整配置对象 const modelFromObject = new ChatOllama({ model: "llama3" }); // 也可以把字符串与其余参数混用 const model = new ChatOllama("llama3", { baseUrl: "http://127.0.0.1:11435" });3. 核心构造参数(ChatOllamaInput)
以下参数均可在new ChatOllama({...})时传入,出处为 chat_models.ts 的接口定义:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
model | string | "llama3" | 要调用的模型名;若本地不存在且开启自动拉取则会先下载 |
baseUrl | string | http://127.0.0.1:11434 | Ollama 服务地址,其次读OLLAMA_BASE_URL环境变量 |
headers | Headers \| Record<string, string> | 无 | 附加到请求的自定义 HTTP 头 |
checkOrPullModel | boolean | false | 调用前是否检查模型本地是否存在,不存在则自动pull |
streaming | boolean | 无 | 是否流式输出 |
format | string \| Record<string, any> | 无 | 指定 JSON 输出("json")或完整 JSON Schema |
fetch | typeof fetch | 全局fetch | 自定义 fetch 实现(代理、鉴权等场景) |
think | boolean | 无 | 是否启用思考模型(如 DeepSeek-R1 等 reasoning 模型)的输出内容 |
4. 运行时调用参数(ChatOllamaCallOptions)
除构造参数外,还可以把参数作为第二个参数传给.invoke、.stream、.batch等 Runnable 方法,或通过.withConfig、.bindTools绑定,出处为 chat_models.ts:
| 参数 | 类型 | 说明 |
|---|---|---|
stop | string[] | 遇到这些字符串即停止生成 |
tools | BindToolsInput[] | 绑定给模型的工具定义 |
format | string \| Record<string, any> | 覆盖构造时的format |
streamUsage | boolean | 是否在流式响应中聚合输出 token 用量,默认true |
tool_choice | never | 已废弃,ChatOllama 不支持指定工具选择 |
5. 底层生成调用链
ChatOllama的调用链非常清晰(见 chat_models.ts):
_generate内部委托给_streamResponseChunks逐个消费流式 chunk,再通过concat聚合为完整AIMessage;_streamResponseChunks调用client.chat({ ...params, messages, stream: true }),逐 chunk 累计prompt_eval_count与eval_count得到usage_metadata,并在最后一个空内容 chunk 中携带完整response_metadata(包含model_provider: "ollama");- 请求参数由
invocationParams统一组装:model、format、keep_alive、think、options(所有模型采样参数)与tools; - 支持通过
options.signal(AbortSignal)在流式过程中中断调用,中断时会调用client.abort()取消底层请求。
四、模型采样参数(OllamaCamelCaseOptions)
ChatOllama、Ollama、OllamaEmbeddings三者的构造参数都扩展自 types.ts 中定义的OllamaCamelCaseOptions。该接口把 Ollama 原生 snake_case 参数映射为 TypeScript 风格的 camelCase,并在invocationParams中重新转为 snake_case 发送给服务端。常用参数如下:
| camelCase 参数 | 转交 Ollama 的字段 | 含义 |
|---|---|---|
numCtx | num_ctx | 上下文窗口大小(token 数) |
numPredict | num_predict | 最多生成的 token 数 |
temperature | temperature | 采样温度 |
topK/topP | top_k/top_p | 采样裁剪参数 |
repeatPenalty | repeat_penalty | 重复惩罚 |
presencePenalty/frequencyPenalty | presence_penalty/frequency_penalty | 存在/频率惩罚 |
seed | seed | 随机种子,固定后结果可复现 |
numGpu/mainGpu | num_gpu/main_gpu | GPU 层数 / 主 GPU 编号 |
numThread | num_thread | 线程数 |
useMmap/useMlock | use_mmap/use_mlock | 内存映射 / 内存锁定 |
keepAlive | keep_alive | 模型驻留内存时间,默认"5m" |
stop | stop | 停止序列列表 |
例如一个更贴近生产的配置:
const model = new ChatOllama({ model: "llama3.1:8b", temperature: 0, numCtx: 8192, numPredict: 512, topP: 0.9, keepAlive: "30m", });五、工具调用(Tool Calling)
ChatOllama.bindTools会把 LangChain 工具转换为 OpenAI 兼容的工具格式后传给 Ollama(见 chat_models.ts):
import { z } from "zod"; const GetWeather = { name: "GetWeather", description: "Get the current weather in a given location", schema: z.object({ location: z.string().describe("The city and state, e.g. San Francisco, CA"), }), }; const llmWithTools = model.bindTools([GetWeather]); const aiMsg = await llmWithTools.invoke( "Which city is hotter today and which is bigger: LA or NY?" ); console.log(aiMsg.tool_calls);模型返回的tool_calls包含工具名、参数与唯一 id,可直接交给 Agent 框架执行并回填ToolMessage继续多轮对话。在消息转换层(utils.ts),LangChain 的AIMessage.tool_calls会被转换为 Ollama 的tool_calls数组,而 Ollama 返回的 tool call 则会转回 LangChain 的tool_call_chunks并补齐 uuid。
六、结构化输出(Structured Output)
withStructuredOutput支持三种模式,底层实现在 chat_models.ts:
functionCalling:把 JSON Schema 包装成单一工具让模型调用,再用createFunctionCallingParser解析;jsonMode:设置format: "json"强制 JSON 输出,再解析为 schema 结构;jsonSchema(默认):直接把完整 JSON Schema 作为format传给 Ollama,由服务端约束输出,再解析。
import { z } from "zod"; const Joke = z.object({ setup: z.string().describe("The setup of the joke"), punchline: z.string().describe("The punchline to the joke"), rating: z.number().optional().describe("How funny the joke is, from 1 to 10"), }); const structuredLlm = model.withStructuredOutput(Joke, { name: "Joke" }); const jokeResult = await structuredLlm.invoke("Tell me a joke about cats"); console.log(jokeResult);单元测试 chat_models.test.ts 覆盖了三种模式的合法输出解析、非法输出抛OutputParserException、自定义工具名(name: "GetName")以及includeRaw: true时返回{ raw, parsed }等场景。集成测试见 chat_models_structured_output.int.test.ts。
七、流式输出与用量元数据
流式调用会逐 token 返回AIMessageChunk:
for await (const chunk of await model.stream(input)) { console.log(chunk); }最后一个空内容 chunk 会携带response_metadata(model、done_reason、total_duration、load_duration、prompt_eval_count、eval_count等 Ollama 统计)与usage_metadata:
const aiMsg = await model.invoke(input); console.log(aiMsg.usage_metadata); // { input_tokens: 19, output_tokens: 20, total_tokens: 39 }流式 chunk 的转换逻辑封装在 utils/stream_events.ts,并有独立的 stream_events 测试 与 chat_models_stream_events.test.ts 验证。
八、Thinking 模型(reasoning)支持
对于带思维链的模型,ChatOllama与Ollama都支持think参数。开启后,流式输出的 token 优先取responseMessage.thinking(思考内容)再取content(正式回答),见 chat_models.ts;同时 Ollama 返回的thinking字段会被写入additional_kwargs.reasoning_content(见 utils.ts)。对应集成测试为 chat_models_think.int.test.ts 与 llms_think.int.test.ts。
九、LLM:Ollama 文本补全模型
对于无需对话上下文的补全场景,可使用Ollama类(llms.ts),默认模型同样是"llama3":
import { Ollama } from "@langchain/ollama"; const ollama = new Ollama({ baseUrl: "http://localhost:11434", model: "llama3", }); const stream = await ollama.stream(`Translate "I love programming" into German.`); const chunks = []; for await (const chunk of stream) { chunks.push(chunk); } console.log(chunks.join(""));它支持与ChatOllama相同的采样参数(numCtx、temperature、topK等),另外还支持多模态:通过运行时参数images传入 base64 图片列表,即可调用 Llava 等视觉模型(见 llms.ts 的OllamaCallOptions)。其_call同样是基于_streamResponseChunks聚合实现。
十、Embeddings:OllamaEmbeddings
OllamaEmbeddings(embeddings.ts)用于把文本转为向量,默认模型为"mxbai-embed-large":
import { OllamaEmbeddings } from "@langchain/ollama"; const embeddings = new OllamaEmbeddings({ model: "mxbai-embed-large", }); const vectors = await embeddings.embedDocuments(["Hello world", "你好世界"]); const queryVec = await embeddings.embedQuery("搜索关键词");核心参数:
| 参数 | 默认值 | 说明 |
|---|---|---|
model | "mxbai-embed-large" | 嵌入模型名 |
baseUrl | http://localhost:11434 | 服务地址,其次读OLLAMA_BASE_URL |
dimensions | 无 | 输出向量维度(按模型支持情况) |
keepAlive | "5m" | 模型驻留时间 |
truncate | false | 是否截断超出上下文窗口的输入 |
requestOptions | 无 | camelCase 的 Ollama 采样参数,内部通过_convertOptions转为 snake_case(见 embeddings.ts) |
headers/fetch | 无 | 自定义请求头与 fetch 实现 |
内部通过this.caller(带maxConcurrency: 1的并发限制器)调用client.embed,并支持失败重试,见 embeddings.ts。集成测试见 embeddings.int.test.ts。
十一、消息转换机制
utils.ts 负责 LangChain 消息与 Ollama 消息的双向转换:
convertToOllamaMessages:按消息类型分发——human/generic转user(支持image_url内容提取 base64 作为多模态images)、ai转assistant(携带tool_calls)、system转system、tool转tool;不支持的类型会抛错;convertOllamaMessagesToLangChain:把 Ollama 消息转回AIMessageChunk,并把thinking写入additional_kwargs.reasoning_content。
这部分逻辑有对应的 utils.test.ts 单元测试保障。
十二、本地开发:安装、构建与测试
如果你想在 langchainjs 仓库内直接开发该包,按照 README 的 Development 章节进行:
1. 安装依赖
pnpm install仓库使用 pnpm workspace 管理,根目录的 pnpm-workspace.yaml 与 package.json 定义了 monorepo 结构。
2. 构建包
在包目录内:
pnpm build或从仓库根目录按 filter 构建:
pnpm build --filter @langchain/ollama构建工具为 tsdown,产物输出到dist/,同时生成 ESM(index.js+index.d.ts)与 CJS(index.cjs+index.d.cts)双格式。
3. 运行测试
测试文件应放在src/下的tests/目录内。单元测试以.test.ts结尾,集成测试以.int.test.ts结尾(集成测试需要本地真实 Ollama 服务与已拉取的模型):
pnpm test # 运行全部单元测试 pnpm test:int # 运行集成测试(需要本地 Ollama)除此之外,该包还接入 LangChain 官方标准测试套件(依赖 internal/standard-tests 包),通过以下命令运行:
pnpm test:standard # 标准单元 + 标准集成 pnpm test:standard:unit # 仅标准单元测试 pnpm test:standard:int # 仅标准集成测试对应测试文件为 chat_models.standard.test.ts 与 chat_models.standard.int.test.ts。
4. 代码检查与格式化
pnpm lint && pnpm format5. 新增导出入口
如需导出新文件:要么在 src/index.ts 中 import 并 re-export,要么把新入口加入 package.json 的exports字段,然后运行pnpm build重新生成入口文件。
十三、结合 LangChain 生态使用
由于ChatOllama、Ollama、OllamaEmbeddings分别实现BaseChatModel、LLM、Embeddings接口,因此可以直接用于 LangChain 生态的各类组合件——RunnableSequence管道、Agent(如 examples/src/createAgent 中的createAgent示例)、提示模板、向量存储检索等。仓库的 examples 目录提供了大量可直接参考的实战示例代码。
总结
@langchain/ollama让"本地大模型 + LangChain.js 应用"的开箱即用成为现实。掌握ChatOllama的构造参数与运行时参数、bindTools工具调用、三种结构化输出模式、think思维链支持,再配合OllamaEmbeddings的向量化能力,即可在完全离线、无 API 费用的前提下搭建完整的 RAG、Agent 与结构化抽取应用。
【免费下载链接】langchainjsThe agent engineering platform项目地址: https://gitcode.com/GitHub_Trending/la/langchainjs
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考