首页/新闻资讯/正文详情

如何用 Genkit + Ollama 搭一套完全离线的文档问答:本地 RAG 实战教程

发布时间:2026/9/24 13:54:49 来源:云帆数科 栏目:资讯中心
如何用 Genkit + Ollama 搭一套完全离线的文档问答:本地 RAG 实战教程
如何用 Genkit Ollama 搭一套完全离线的文档问答本地 RAG 实战教程【免费下载链接】genkitOpen-source framework for building agentic apps in JavaScript, Go, Dart, and Python, built and used in production by Google项目地址: https://gitcode.com/GitHub_Trending/ge/genkit本文基于 Genkit 仓库中的 Ollama 示例js/testapps/ollama带你接好 genkitx-ollama 插件、用 nomic-embed-text 做嵌入、内存余弦相似度检索、phi3.5 生成搭出一条完全离线的本地 RAG 问答链路并能在 Dev UI 中直接运行调试。数据出不了内网本地 RAG 为什么是首选先说结论如果你的文档不能离开内网、不想按 token 付费、或者干脆要离线可用本地 RAG 几乎是唯一务实的选择。RAGRetrieval-Augmented Generation检索增强生成的原理很简单就三步嵌入把每份文档转成一个向量。你可以把 embedding 理解成把文本变成一组可以算距离的数字检索用户问题也转成向量和文档向量比距离余弦距离越小语义越接近生成把检索出的几条文档塞进 prompt让模型基于上下文回答。Genkit 仓库里有一条现成的完整链路可以直接照着跑js/testapps/ollama示例内置了 5 条宝可梦描述Pikachu、Charmander、Bulbasaur、Squirtle、Jigglypuff用nomic-embed-text生成 768 维嵌入在内存里做余弦相似度取 Top-3再交给phi3.5:latest生成回答。除了本地跑着一个 Ollama 服务整个过程不依赖任何云端 API。一套本地环境Ollama、Node 18 与两个模型的拉取这一步要准备两样东西Node.js18 及以上版本示例基于tsx与tsc运行Ollama本地模型服务端负责嵌入和文本生成。️ 安装 Ollama 后启动服务并拉取模型ollama serve ollama pull nomic-embed-text ollama pull phi3.5:latestollama serve默认监听http://localhost:11434这个地址同时也是 Genkit Ollama 插件在未配置serverAddress时的默认值。模型角色用途nomic-embed-text嵌入模型把宝可梦描述和用户问题转成 768 维向量phi3.5:latest生成模型基于检索到的上下文产出最终回答示例的genkit与genkitx-ollama都以workspace:*形式依赖 monorepo 内的本地包见 js/testapps/ollama/package.json所以不需要单独安装插件。⚠️ 注意运行时报Make sure the Ollama server is running.时先确认ollama serve是否在跑。插件对 Ollama 的请求一旦失败就会抛出这句话见 js/plugins/ollama/src/index.ts。最小可运行配置5 行代码把 Genkit 接到 Ollama核心配置长这样完整源码见 js/testapps/ollama/src/index.tsimport { genkit, z } from genkit; import { ollama } from genkitx-ollama; const ai genkit({ plugins: [ ollama({ embedders: [{ name: nomic-embed-text, dimensions: 768 }], }), ], });插件支持的全部参数定义在 js/plugins/ollama/src/types.ts 的OllamaPluginParams中若与仓库当前版本不符以源码为准参数必填说明models否声明要注册的生成模型如[{ name: gemma }]可带type: chat \| generate默认chat和supports.toolsembedders用嵌入时必填namedimensions必须都提供初始化时注册为ollama/nameactionserverAddress否默认http://localhost:11434requestHeaders否静态对象或异步函数函数会收到{ serverAddress, model, modelRequest?, embedRequest? }适合动态注入鉴权 token示例里还额外挂了一个requestHeaders函数打印serverAddress后返回一个模拟的Authorization: Bearer头——这就是动态鉴权的标准写法把my-token换成真实 token 获取逻辑即可。引用模型和嵌入器有两个便捷函数ollama.model(phi3.5:latest) // - ModelReferenceollama/phi3.5:latest ollama.embedder(nomic-embed-text) // - ollama/nomic-embed-text它们内部只是把名字拼成ollama/name形式的 action 名。这里有个值得知道的细节生成模型是动态解析的——你本地ollama pull过任何模型都可以通过ollama.model(模型名)直接调用不必在models里声明而嵌入器必须提供dimensions所以要在embedders里显式注册。一个问题变成答案的三段路径示例把 RAG 拆成三个独立函数全部在 js/testapps/ollama/src/index.ts 中。第一段给每份文档生成嵌入pokemon.embedding ( await ai.embed({ embedder: ollama.embedder(nomic-embed-text), content: pokemon.description, }) )[0].embedding;ai.embed返回嵌入结果数组示例取[0]拿到唯一那个向量。底层行为插件把文本组装成{ model, input }请求体 POST 到 Ollama 的/api/embed再把响应里的payload.embeddings逐个包成{ embedding }返回实现见 js/plugins/ollama/src/embeddings.ts。第二段内存里算 Top-3 余弦距离findNearestPokemon的检索策略很朴素教学价值很高先做完整性校验只要还有记录的embedding是null直接抛Some Pokemon are not yet embedded对每条记录算余弦距离升序排序取前topN 3条余弦距离 1 - 点积 / (|a| × |b|)越小语义越近遇到零向量会抛Invalid input: zero vector。第三段带着上下文生成回答return await ai.generate({ model: ollama.model(phi3.5:latest), prompt: Given the following context on Pokemon:\n${pokemonContext}\n\nQuestion: ${question}\n\nAnswer:, });关键点有两个用户问题也要先过一遍嵌入模型才能和文档向量在同一语义空间里比距离检索出的 3 条记录被拼成名字: 描述的上下文块塞进 prompt。最终答案从response.text取。⚠️ 注意示例每次执行 Flow 都会对全部 5 条记录重新嵌入。演示无所谓但真实项目里文档索引应该是一次性离线任务运行时只嵌入查询语句。把 RAG 包成 Flow用 Dev UI 直接跑起来export const pokemonFlow ai.defineFlow( { name: Pokedex, inputSchema: z.string(), outputSchema: z.string(), }, async (input) { await embedPokemon(); const response await generateResponse(input); return response.text; } );inputSchema/outputSchema用 Zod 声明带来两个好处Dev UI 里有结构化的输入输出表单运行时也会做参数校验。进入js/testapps/ollama目录启动pnpm run genkit:dev再开另一个终端genkit ui:start 示例的脚本含义见 js/testapps/ollama/package.json脚本命令作用genkit:devgenkit start -- tsx --watch src/index.ts热重载运行入口由 Genkit CLI 托管devtsx --watch src/index.ts不经过 Genkit CLI 的纯开发运行buildtsc编译 TypeScript 到lib/startnode lib/index.js运行编译产物Dev UI 里能看到两个 FlowPokedex是完整的 RAG 入口输入一个自然语言问题比如问哪只宝可梦擅长电系攻击就能看到完整的检索生成链路joker则演示了两个进阶能力——运行时通过model参数动态换模型默认gemma3:latest以及用onChunk: sendChunk把ai.generate的增量片段实时转发给调用方实现流式输出。插件背后Genkit 配置与 Ollama HTTP API 的映射想把示例改造到自己的项目里搞清楚插件底层行为很有帮助。OllamaConfigSchemajs/plugins/ollama/src/index.ts在 Genkit 通用生成配置之上扩展了 Ollama 特有参数映射关系如下默认值来自插件源码描述若与仓库当前版本不符以源码为准Genkit 配置项映射到 Ollama options默认值 / 范围temperaturetemperature0.80.0 ~ 1.0topKtop_k40topPtop_p0.90 ~ 1.0stopSequencesstop多值用空串连接成一个字符串—maxOutputTokensnum_predict—也就是说ai.generate({ config: { temperature: 0.2 } })就能直接控制采样。端点选择由模型的type决定type: chat默认→POST /api/chat走多轮 messages图片会自动剥掉 data URI 前缀再发送工具调用tool_calls也只有 chat API 支持type: generate→POST /api/generateprompt 与 system 消息被分别提取到prompt/system字段。工具方面有个硬限制工具的inputSchema必须是 object 类型否则插件会抛Unsupported tool: ... Ollama only supports tools with object inputs。另外两个底层行为值得知道动态发现插件的listActions会调用 Ollama 的GET /api/tags拉取本地已装模型朴素地过滤掉名字里含 embed 的把其余模型暴露为ollama/nameaction流式读取流式请求通过res.body.getReader()逐块读取解析 Ollama 返回的 NDJSON 流后回调onChunk。动手清单把示例推向生产的 5 个改法索引与检索分离把embedPokemon()挪进一次性脚本或定时任务运行时只对查询语句做嵌入换掉内存线性扫描数据量上来后接向量存储仓库里已有 js/plugins/pinecone/、js/plugins/dev-local-vectorstore/ 等插件可参考换模型零成本ollama pull新模型后在插件配置的models/embedders里声明即可业务代码不用动调采样参数在ai.generate的config里传temperature/topK/topP按问题类型收紧或放松输出用 Dev UI 盯召回质量跑Pokedex时查看每个节点的输入输出与耗时定位是检索召回不准还是生成质量差。【免费下载链接】genkitOpen-source framework for building agentic apps in JavaScript, Go, Dart, and Python, built and used in production by Google项目地址: https://gitcode.com/GitHub_Trending/ge/genkit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关推荐

光伏输出光耦驱动MOSFET:直流固态开关设计指南
光伏输出光耦驱动MOSFET:直流固态开关设计指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 13:54:42

ToastFish 碎片时间背单词完整指南:10 分钟完成第一次有效学习
ToastFish 碎片时间背单词完整指南:10 分钟完成第一次有效学习

ToastFish 碎片时间背单词完整指南:10 分钟完成第一次有效学习 【免费下载链接】ToastFish 一个利用摸鱼时间背单词的软件。 项目地址: https://gitcode.com/GitHub_Trending/to/ToastFish 坐在地铁里、隔着会议间隙看一眼屏幕,这些 10 到 20 秒的… · 2026/9/24 13:54:30

LLC谐振变换器调试实战:从炸管到ZVS,ICE2HS01G参数与波形全解析
LLC谐振变换器调试实战:从炸管到ZVS,ICE2HS01G参数与波形全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 13:54:12

告别Miscellaneous:打造个人杂项收集与归档系统的实操指南
告别Miscellaneous:打造个人杂项收集与归档系统的实操指南

前阵子整理硬盘和学习笔记时,我发现自己散落着大量“不知道放哪、但又不能删”的东西。一张截图、一段摘抄、一份临时文档、一个随手记下的灵感,它们全都被塞进了一个叫“Miscellaneous”的文件夹里。结果不到两个月,这个文件夹就变成了一座垃… · 2026/9/24 21:33:16

告别杂项黑洞:从Miscellaneous到高效信息整理的完整实践
告别杂项黑洞:从Miscellaneous到高效信息整理的完整实践

我做了快十年的内容与信息管理,电脑里最不敢打开的就是那个名为“Miscellaneous”的文件夹。它像一个黑洞,吞掉所有暂时不知道往哪里放的东西:随手截的图、半年前的合同扫描件、突然灵光一闪的构思草稿、下载完就再也没碰过的软件安装包。每次… · 2026/9/24 21:33:16

Python多进程+多线程并发处理Redis与Kafka数据实战
Python多进程+多线程并发处理Redis与Kafka数据实战

我最早写这个脚本的场景,其实特别朴素:业务方丢过来一堆需求,要从Redis的队列里捞数据做清洗,再从Kafka的topic里消费一批日志做指标统计,而且数据量不小,单机跑一条线程根本吃不完。试过先写脚本串行跑&am… · 2026/9/24 21:33:16

宁夏口碑好的央国企职业规划机构选择指南
宁夏口碑好的央国企职业规划机构选择指南

在宁夏打算求职央国企,想要找靠谱的职业规划机构应该怎么选?这是很多打算进入央国企发展的宁夏大学生,都会反复搜索的问题。央国企素来以稳定的薪资、完善的福利保障,成为应届毕业生求职的热门方向,不少同学从大一开始就筹备求职… · 2026/9/24 21:33:16

STM32 自学笔记 02
STM32 自学笔记 02

# GPIO #软件平台 STM32CubeIde#软件包 STM32Cube_FW_F0_V1.11.6#系统平台 Win7初始化:void MX_GPIO_Init(void) {GPIO_InitTypeDef GPIO_InitStruct {0};/* GPIO Ports Clock Enable */__HAL_RCC_GPIOC_CLK_ENABLE();__HAL_RCC_GPIOF_CLK_ENABLE();__HAL_RCC_GPIO… · 2026/9/24 21:33:16

Claude Opus 5.5 深度解析:旗舰能力、定价革命与国内接入实战指南
Claude Opus 5.5 深度解析:旗舰能力、定价革命与国内接入实战指南

摘要2026 年 9 月 22 日,Anthropic 正式发布 Claude Opus 5.5,作为 Claude 5.5 系列的首款旗舰模型,它在多数工作任务上达到顶级旗舰 Claude Fable 5.1 的水平,在智能体编码、计算机操作、知识工作等多项基准测试中全面领先。更值… · 2026/9/24 21:33:10

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程
基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为… · 2026/9/24 0:00:13

1D-CNN时间序列建模实战:从Conv1d原理到工业落地
1D-CNN时间序列建模实战:从Conv1d原理到工业落地

简介:面向时间序列数据建模的一维卷积神经网络完整实现,适合深度学习入门者及需要快速验证时序模型的研究者,能够从音频、文本、传感器或股价等序列中挖掘局部特征与时间依赖。压缩包体积很小,只有3KB,内含3个Python脚… · 2026/9/24 0:00:26

柔软的L:汉语语流中被忽视的舌肌张力控制
柔软的L:汉语语流中被忽视的舌肌张力控制

1. 这个“L”不是字母表里的L,而是舌尖上的L最近在几个方言群和语音教学社群里,反复看到有人发一句:“也说字母L:柔软的长舌”。初看以为是英语发音课笔记,点开才发现全是方言爱好者、播音系学生、语言康复师甚至戏曲演… · 2026/9/24 0:00:44

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码