@kognitivedev/rag, 用js做AI Agent开发

40岁了,最近再学bun。

你是不是也想转 AI Agent 开发,却被满屏 Python/PyTorch/LangChain 劝退?听过 RAG,却觉得那是算法工程师才懂的"黑魔法"?手里只会 JS/TS,完全不知道从哪下手?

你不是一个人。这篇文章用一段能直接跑的 TS 代码,把 RAG 讲清楚。你看完就会明白:不是只有 Python 才能玩 AI,JS 一样能干。

javascript 复制代码
    
    
    
  // ① 引入 RAG 三件套:管道、向量库、切块器
import { DocumentPipeline, InMemoryVectorStore, RecursiveTextChunker } from "@kognitivedev/rag";
// ② AI SDK 适配器,把百炼 embedding 包成统一接口
import { AISDKEmbeddingProvider } from "@kognitivedev/adapter-ai-sdk";
// ③ 用 OpenAI 兼容格式连接百炼
import { createOpenAI } from "@ai-sdk/openai";

const qwen = createOpenAI({
  baseURL: "https://dashscope.aliyuncs.com/compatible-mode/v1", // 百炼兼容端点
  apiKey: "sk-你的百炼API-KEY",
});

// ④ 组装 RAG 流水线
const agent = new DocumentPipeline({
  chunker: new RecursiveTextChunker(),                              // 文档怎么切
  embedder: new AISDKEmbeddingProvider({
    model: qwen.embedding("text-embedding-v4")                     // 用什么模型转向量
  }),
  vectorStore: new InMemoryVectorStore(),                           // 向量存在哪
});

// ⑤ 喂文档、建索引
await agent.ingest([{ content: "公司规定:离职需提前30天申请。" }]);
// ⑥ 提问并检索最相似的块
const results = await agent.search("怎么离职?");
console.log(results[0].content); // 公司规定:离职需提前30天申请。
sql 复制代码
    
    
    
  bun add @kognitivedev/rag @ai-sdk/openai ai @kognitivedev/adapter-ai-sdk

API KEY 从这里申请:阿里云百炼控制台

阿里注册送100万Token,正好用来测试。

上面这 8 行代码,已经能跑通一个最小的 RAG 流程。下面解释它到底干了什么。

一、核心概念(一句话搞懂)

  • RAG:先翻书,再回答。让 AI 基于你的文档说话。
  • Agent:能自主决策、调用工具的智能体。RAG 是它的"检索工具"。
  • Embedding:文本→向量(一串数字),让计算机能算"相似度"。
  • Vector Store:存向量的数据库,负责快速找最像的那几段。

二、RAG 干了什么?(代码透视)

ini 复制代码
    
    
    
  // 你的文档
const doc = "公司规定:离职需提前30天申请。";

// ① 切块(Chunking)------ 把长文切成小段
const chunks = ["公司规定:离职需提前30天申请。"];

// ② 向量化(Embedding)------ 文字→数字指纹
const vector = [0.123, -0.456, 0.789, /* ... */]; // 1024维或更多

// ③ 存库(Store)------ 入库备查
await store.add({ content: chunks[0], vector });

// ④ 检索(Search)------ 问题也转向量,找最像的
const question = "怎么离职?";
const qVector = [0.111, -0.222, 0.333, /* ... */];
const similar = await store.find(qVector, { topK: 1 });
// → "公司规定:离职需提前30天申请。"

三句话总结:文档切块→转向量→存库。问题来了→转向量→找最像的块→拿去给 AI。

三、怎么用?

javascript 复制代码
    
    
    
  import { DocumentPipeline, InMemoryVectorStore, RecursiveTextChunker } from "@kognitivedev/rag";
import { AISDKEmbeddingProvider } from "@kognitivedev/adapter-ai-sdk";

// 三个积木,随便换
const pipeline = new DocumentPipeline({
  chunker: new RecursiveTextChunker(),              // 怎么切
  embedder: new AISDKEmbeddingProvider({            // 怎么转向量
    model: qwen.embedding("text-embedding-v4")
  }),
  vectorStore: new InMemoryVectorStore(),           // 存哪
});

await pipeline.ingest([{ content: "你的文档" }]);   // 自动完成 切→转→存
const results = await pipeline.search("你的问题");   // 自动完成 转→找→返回

Chunker 不是只能递归切。长文档用 MarkdownChunker,按标题切;按 Token 预算切用 TokenChunker;HTML、JSON、句子都有对应实现。

php 复制代码
    
    
    
  import { MarkdownChunker, TokenChunker, SentenceChunker } from "@kognitivedev/rag";

// 按 Markdown 标题切,适合文档站点
const mdChunks = new MarkdownChunker().chunk({
  content: "# 入职\n\n办工卡。\n\n# 离职\n\n提前30天申请。",
});

// 按 Token 预算切,适合超长文本
const tokenChunks = new TokenChunker({ tokensPerChunk: 512, overlap: 50 }).chunk({
  content: "A".repeat(10000),
});

// 按句子边界切,适合法律文书
const sentenceChunks = new SentenceChunker({ maxChunkSize: 200 }).chunk({
  content: "第一条 合同期限一年。第二条 提前30天通知。",
});

换数据库(内存→Redis):

arduino 复制代码
    
    
    
  // 开发
vectorStore: new InMemoryVectorStore()

// 生产(换这一行就行)
vectorStore: new RedisVectorStore(redisClient)

换模型(百炼→OpenAI):

css 复制代码
    
    
    
  import { openai } from "@ai-sdk/openai";

// 只改这一行
embedder: new AISDKEmbeddingProvider({
  model: openai.embedding("text-embedding-3-small")
})

四、批量入库记得带 metadata

真实文档不会只有一条。ingest 时带上 metadata,后面可以按部门、标签、版本号过滤。

less 复制代码
    
    
    
  const result = await pipeline.ingest([
  { content: "研发部:代码评审每周五下午。", metadata: { dept: "研发部" } },
  { content: "人力资源部:年假按工龄计算。", metadata: { dept: "人力资源部" } },
  { content: "人力资源部:离职需提前30天申请。", metadata: { dept: "人力资源部" } },
]);

console.log(result);
// { documentsProcessed: 3, chunksCreated: 3, vectorsStored: 3 }

metadata 会跟着向量一起存,检索结果里也能取到,方便做来源标注和权限控制。

五、搜索参数要会调

search 不是只能传字符串。topKminScore 决定召回质量,生产级向量库(Redis、PgVector、Qdrant)还支持 filter 按 metadata 过滤。

ini 复制代码
    
    
    
  const results = await pipeline.search("年假多少天?", {
  topK: 5,          // 返回前 5 个结果
  minScore: 0.5,    // 相似度低于 0.5 的不要
});

console.log(results.map(r => ({
  content: r.content,
  score: r.score,
})));

minScore 过低会召回垃圾内容,过高可能漏答案。先用默认值跑通,再按数据特点微调。

六、检索完让大模型说人话

RAG 只负责找资料,生成答案还得靠大模型。下面把检索结果拼进 prompt,交给百炼的 qwen-plus

javascript 复制代码
    
    
    
  import { generateText } from "ai";

const docs = await pipeline.search("怎么离职?", { topK: 3 });
const context = docs.map(d => d.content).join("\n\n");

const { text } = await generateText({
  model: qwen.chat("qwen-plus"),
  prompt: `根据以下资料回答问题:\n\n${context}\n\n问题:怎么离职?`,
});

console.log(text);

实际项目里,建议把 prompt 模板化,并加上"如果资料里没有,就说不知道"的约束,避免 hallucination。

七、进阶用法(让 Agent 自己决定是否检索)

ini 复制代码
    
    
    
  // 把 RAG 包装成一个"工具",Agent 可以自主决定何时调用
const retrievalTool = pipeline.asTool();

// Agent 看到问题后,自己判断:要不要翻书?
const response = await agent.chat({
  messages: [...],
  tools: [retrievalTool],  // 给 Agent 配个"书库"
});

八、三个关键认知

arduino 复制代码
    
    
    
  // 认知1:RAG ≠ 微调
// 微调 = 让 AI 背新知识(贵,慢,要数据)
// RAG   = 让 AI 考试时翻书(便宜,快,实时更新)

// 认知2:RAG = 检索 + 生成
// 检索 = 找资料(解决问题"记不住")
// 生成 = 说人话(解决问题"说不清")

// 认知3:RAG 是 Agent 的"外部大脑"
// Agent 负责决策,RAG 负责提供素材

九、模型从哪来?(云端 vs 本地)

php 复制代码
    
    
    
  // 云端(不会下载模型)
const embedder = new AISDKEmbeddingProvider({
  model: qwen.embedding("text-embedding-v4")
});
// → 发请求到阿里云百炼,云端算完返回结果

// 本地(会自动下载模型)
import { embed } from "ollama";
await embed({ model: "nomic-embed-text", input: "文档" });
// → 首次运行下载几百 MB 到 ~/.ollama/models

云端适合快速验证和生产,本地适合数据不出内网的场景。新手建议先走云端,跑通了再考虑本地化。

十、两个常见坑

坑 1:向量维度对不上。 text-embedding-v4 默认 1024 维,text-embedding-v3 默认也是 1024 维,但 OpenAI 的 text-embedding-3-small 是 1536 维。不同 embedding 模型混用时,向量库必须清空重建,否则检索会报错。

坑 2:文档太短反而搜不到。 如果切的 chunk 只有几个字,embedding 的语义特征很弱,搜"年假"可能匹配到"年假",但搜"带薪休假"就漏了。建议 chunk 至少包含一个完整句子或一段完整语义。

十一、术语速查

术语 读音(拼音) 一句话解释
Agent ài zhēn tè 能自主决策的智能体
RAG ruì gé 先检索再生成
Embedding ēn bèi dīng 文本→向量数字
Vector wéi kè tè 一串数字表示语义
Vector Store wéi kè tè sī duō 向量数据库
Chunk chāng kè 切出来的文本块
Prompt pǔ ràng pǔ tè 给 AI 的指令
ingest yīn jié sī tè 摄入文档建索引
search sè chí 检索相似内容
Top-K tāo pǔ kāi 返回前 K 个结果

总结

    1. RAG = 先翻书再回答
    1. Agent = 自主决策的智能体,RAG 是它的工具

我在准备下一篇:AI 只会"知道"还不够,得让它"能做"------理解 MCP, 关注我哦。

相关推荐
IT_陈寒1 小时前
JavaScript的默认参数挖坑实录,我掉进去了
前端·人工智能·后端
陈明勇2 小时前
Go 1.26 新特性回顾:语言增强、工具升级与 Green Tea GC 默认启用
后端·go
咖啡八杯12 小时前
GoF设计模式——策略模式
java·后端·spring·设计模式
lizhongxuan13 小时前
AI Agent 上下文压缩利器 Headroom
后端
kyriewen13 小时前
别再 console.log 了:5 个 Chrome DevTools 调试技巧,用过就回不去了
前端·javascript·面试
Csvn15 小时前
SSH 远程管理与安全加固 — 运维的守门之道
后端
IT_陈寒15 小时前
Python搞不定字符串编码?这破玩意坑我两小时!
前端·人工智能·后端
To_OC15 小时前
LC 1 两数之和:面试第一道必考题,暴力解法直接被面试官 pass
javascript·算法·leetcode
菜鸟谢17 小时前
Rust 智能指针完整详解
后端