菜鸟AI - 让提示词生成更简单! 全站导航 全站导航
AI工具安装 新手教程 进阶教程 辅助资源 AI提示词 热点资讯 技术资讯 产业资讯 内容生成 模型技术 AI信息库

已有账号?

首页 > AI教程 > 类低代码平台Agent开发实践:文档助手从零入门到精通实战指南
进阶教程 综合资讯

类低代码平台Agent开发实践:文档助手从零入门到精通实战指南

2026-06-01
阅读 0
热度 0
作者 菜鸟AI编辑部
摘要

摘要

类低代码平台Agent开发中,文档助手通过RAG流程实现智能问答。技术选型采用ChromaDB向量库

最近正在开发仿真平台的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: `http://${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;
}

分词

文本分块推荐使用LangChain社区提供的 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: `http://${config.chromaHost}:${config.chromaPort}`,
}).catch((error) => {
  console.error("Error creating vector store:", error);
  throw error;
});

这一步的耗时取决于文档规模和嵌入模型算力。文档内容更新时,务必实现增量 embedding 机制,避免全量重算带来的性能损耗。

查询

查询阶段同样需要将用户输入转为向量,不过 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的prompt
const prompt = buildPrompt(
  query,
  contextDocs,
  projectContext,
  conversationHistory
);
const response = await llm.invoke(prompt);

来源:互联网

免责声明

本网站新闻资讯均来自公开渠道,力求准确但不保证绝对无误,内容观点仅代表作者本人,与本站无关。若涉及侵权,请联系我们处理。本站保留对声明的修改权,最终解释权归本站所有。

同类文章推荐

相关文章推荐

更多