游乐游手机版
首页/AI教程/文章详情

类低代码平台Agent开发实践:文档助手(上)

时间:2026-06-01 16:49
类低代码平台Agent开发中,文档助手通过RAG流程实现智能问答。技术选型采用ChromaDB向量库,嵌入模型改为Qwen3-Embedding以适配中文。流程包括文档载入、RecursiveCharacterTextSplitter分词、Chroma向量化存储及相似度检索,检索结果经LLM生成回答。
```html

最近在搭建仿真平台的智能Agent时,我逐渐发现它的场景构建与开发思路,与大多数低代码平台其实有着异曲同工之妙。因此,这里整理一下自己的实践经验,将Agent的功能大致划分为两大模块:文档助手与智能生成。

类低代码平台的Agent开发实践(上)——文档助手

本文先重点探讨文档助手这一模块。

文档助手

低代码类平台通常配置项繁多、操作手册厚重、案例也五花八门——这些恰恰是智能文档助手最能大显身手的地方。

技术选型

在RAG(检索增强生成)这部分,我最终选定的核心技术是ChromaDB。

import { Chroma } from "@langchain/community/vectorstores/chroma";
function getVectorStore(): Promise<Chroma> {
  if (vectorStore) {
    return vectorStore;
  }
  vectorStore = new Chroma(embeddings, {
    collectionName: COLLECTION_NAME,
    url: `https://${config.chromaHost}:${config.chromaPort}`,
  });
  return vectorStore;
}

ChromaDB 虽然内置了嵌入模型(all-MiniLM-L6-v2),但我换成了 Qwen3-Embedding-8B,它在中文场景下的表现明显更优。如果你的知识库中包含较多图片,则可以试试 Qwen3-VL-Embedding-8B——不过这个模型的部署有一定门槛,要么调用阿里云的API,要么准备一台性能较好的机器进行本地部署,目前Ollama还不支持直接运行这种多模态模型。

import { OpenAIEmbeddings } from "@langchain/openai";
import { config } from "../config/index.js";
export const embeddings = new OpenAIEmbeddings({
  model: config.embeddingModel,
  batchSize: 8,
  timeout: 300_000,
  configuration: {
    baseURL: config.embeddingBaseUrl,
  },
});

RAG 流程

RAG的标准流程大家应该不陌生:加载文档 → 文本切分 → 向量嵌入 → 向量存储 → 检索回答。下面我们来逐步分解。

加载文档

function loadDocuments(): Promise<Document[]> {
  const files = await getFiles(DOCS_PATH);
  const documents: Document[] = [];
  for (const file of files) {
    const rawContent = await readFile(file, 'utf-8');
    // 若非纯文本(如 Excel、HTML),须先转换为纯文本格式
    const text = convert(rawContent);
    documents.push(
      new Document({
        pageContent: text,
        metadata: {
          source: file,
          title,
        },
      })
    );
  }
  return documents;
}

文本切分

分词工具推荐使用 RecursiveCharacterTextSplitter(来自 @langchain/textsplitters)。

import { RecursiveCharacterTextSplitter } from '@langchain/textsplitters';
import type { Document } from '@langchain/core/documents';

const CHUNK_SIZE = 1000;
const CHUNK_OVERLAP = 200;

export function createSplitter(): RecursiveCharacterTextSplitter {
  return new RecursiveCharacterTextSplitter({
    chunkSize: CHUNK_SIZE,
    chunkOverlap: CHUNK_OVERLAP,
  });
}

export async function splitDocuments(docs: Document[]): Promise<Document[]> {
  const splitter = createSplitter();
  return splitter.splitDocuments(docs);
}

简单说明一下它的核心原理,本质上是“分级降级,尽力而为”:

  1. 按优先级切分:先用较高的分隔符(比如段落分隔符 \n\n)尝试切分,尽量维持段落完整性。
  2. 检查块大小:如果某个切分后的块仍然超过预设的 chunk_size,并不会硬性截断,而是继续向下处理。
  3. 递归降级处理:对超长的块自动降级,采用更低优先级的分隔符(如句号 .)再次切分。
  4. 循环直至完成:不断递归,直到所有块都符合大小要求。如果最终使用最小分隔符(单个字符 "")仍超长,则只能生成一个超长块,并抛出警告。

基于这一原理,我们还可以额外加入一些中文标点作为分隔符:

export function createSplitter(): RecursiveCharacterTextSplitter {
  return new RecursiveCharacterTextSplitter({
    separators: [
      "\n\n", // 段落分隔
      "\n",   // 换行符
      "。",
      "!",
      "?",
      ";",  // 中文句子结束符
      ",",
      "、",  // 中文逗号/顿号
      " ",  // 空格
      "",    // 字符级别
    ],
    chunkSize: CHUNK_SIZE,
    chunkOverlap: CHUNK_OVERLAP,
  });
}

向量嵌入与存储

Chroma.from_documents() 是一个将向量化和存储两步合并的便捷方法。调用时,内部会自动执行:

  1. 调用嵌入模型:对传入的每个 Document 的文本内容转换为向量。
  2. 存入数据库:建立 Chroma 连接,将向量连同原始文本和元数据一起存储,形成完整的向量数据库。
const store = await Chroma.fromDocuments(docs, embeddings, {
  collectionName: COLLECTION_NAME,
  url: `https://${config.chromaHost}:${config.chromaPort}`,
}).catch((error) => {
  console.error("向量存储创建失败:", error);
  throw error;
});

这一步的耗时取决于文档数量和嵌入模型,可能很长。当文档更新时,最好能支持增量式的嵌入更新。

查询检索

查询时同样需要将原始字符串转换为向量,不过 similaritySearch 会自动完成这一转换。

const llm = createLLM(0.3);
const docs: Document[] = await vectorStore.similaritySearch(query, 5);
const contextDocs: string[] = docs.map((doc: Document) => doc.pageContent);
// 源文档可用作引用链接
const sources: string[] = [...new Set(docs.map((doc: Document) => doc.metadata.source as string))];
// 将向量数据库检索出的内容注入到LLM的提示词中
const prompt = buildPrompt(
  query,
  contextDocs,
  projectContext,
  conversationHistory
);
const response = await llm.invoke(prompt);
```
来源:https://juejin.cn/post/7645900195422978074
上一篇公文写作:提升职场沟通效率的重要性与实用技巧 下一篇AI Time Machine虚拟形象功能评测
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
OpenClaw浏览器自动化控制 Playwright MCP与Mcporter方案实现完整流程步骤详解教程
AI教程 · 2026-06-01

OpenClaw浏览器自动化控制 Playwright MCP与Mcporter方案实现完整流程步骤详解教程

概述 这篇文章记录了把Playwright MCP集成到OpenClaw中,并用Mcporter作为中间桥梁的完整测试过程。内容包括问题诊断、架构理解,以及正确的使用方法——说白了,就是带大家把整个链路彻底捋清楚。 先交代一下背景:为啥折腾这个方案?说实话,就是熬夜后闲得慌,突发奇想想在家里搞搞Op

AI写业务代码后必须坚持的过程控制
AI教程 · 2026-06-01

AI写业务代码后必须坚持的过程控制

前言AI 已经能极其高效地帮我们搞定业务代码了。这个结论经过反复验证,基本上没什么悬念。但问题也随之而来:越是这样,越容易陷入失控状态——想到哪写到哪,总盼着 AI 一口气把活儿全干了。业务代码和 demo 最大的不同在于,业务从来不是孤立的。它牵扯着一连串的业务流程、历史包袱、数据状态、权限边界、

我用两个高效技巧解决AI开发文档记录难题
AI教程 · 2026-06-01

我用两个高效技巧解决AI开发文档记录难题

我用 AI 写了三个月代码,结果连自己写的东西都看不懂了 一个开发者的普遍困境 从去年开始,大量开发者涌入 Claude Code 进行 AI 辅助开发。效率提升令人振奋——过去需要两天的功能,现在一个下午就能搞定。但很快,一个尴尬的问题浮出水面:三个月前自己写的代码,如今竟然看不懂了。 问题不在于

AI改坏真实App的常见问题与解决技巧
AI教程 · 2026-06-01

AI改坏真实App的常见问题与解决技巧

探索AI辅助移动端开发的过程中,我属于较早深入实践并持续积累经验的那一批。过去几个月里,我几乎每天都会在真实的iOS与Flutter项目中与AI协作调整代码:涵盖SDK封装、旧代码迁移、Demo补全、使用文档优化、多语言适配、界面检查、验证执行以及工作交接整理。因此,本文无意纠缠“AI究竟能否编写代

领导要求部署OpenClaw?先看这篇指南
AI教程 · 2026-06-01

领导要求部署OpenClaw?先看这篇指南

前几天,领导丢过来一句话:你去看一下 OpenClaw,评估一下能不能在公司内部部署。紧接着又问了一个很典型的问题:这东西到底算什么?是一种云服务吗? 仔细一想,这个问题的答案并不简单。OpenClaw 本身不等于“云平台”,但一旦真正用起来,云环境通常会深度参与。它更像一层编排和运行框架,负责把袋