预备好node,pnpm环境。

初始化项目

先创立一个空的文件夹langchain-demo,执行指令以下指令初始化一个项目。

cd langchain-demo/
pnpm init

接下来,咱们预备一个测试数据,然后将数据摄取到向量数据库中。详细步骤如下: 首先在根目录下创立一个 ingest-data.js 然后在项目根目录下执行如下指令:

# 装置LangChain
pnpm i langchain

装置完结后:修正package.json文件,如图所示,增加"type": "module"

基于自定义数据源的LangChain的聊天

读取数据

预备数据

先预备一个markdown格式的文件。能够直接在网上找一个,比方Vue3的官方文档。然后在页面文档选中一部分,翻开F12经过输入指令$0.innerHTML并回车后即可取得数据。简单如图所示:

基于自定义数据源的LangChain的聊天

基于自定义数据源的LangChain的聊天

或许自行预备数据也可。 将网页中爬取的文本内容copy到 html-to-markdown网站上,转化成markdown。并将转化后的文件放在项目根目录下的vue3-document.md中,如图所示

基于自定义数据源的LangChain的聊天

读取数据

修正咱们在之前现已预备好的文件ingest-data.js,文件内容如下:

// 读取markdown文件
import { UnstructuredLoader } from "langchain/document_loaders/fs/unstructured";
// 实例化  并传入数据的途径
const unstructuredLoader = new UnstructuredLoader("./vue3-document.md");
// 读取文件,这是个promise 运用await
const docs = await unstructuredLoader.load()
console.log(docs)

然后经过如下指令进行验证:

cd langchain-demo/
node ingest-data.js

执行成功成果如图所示:

基于自定义数据源的LangChain的聊天

切开数据

持续编写ingest-data.js详细如下:

// 1. 读取markdown文件
import { UnstructuredLoader } from "langchain/document_loaders/fs/unstructured";
// 2. 文档拆分,将文档拆分红一块一块的
// 2.1 导入langchain提供的拆分东西
import { RecursiveCharacterTextSplitter } from "langchain/text_splitter"
// 1.1 实例化UnstructuredLoader  并传入数据的途径
const unstructuredLoader = new UnstructuredLoader("./vue3-document.md");
// 1.2 读取文件,这是个promise 运用await
const rawDocs = await unstructuredLoader.load()
// 1.3
console.log(rawDocs)
// 2.2 实例化 RecursiveCharacterTextSplitter
const splitter = new RecursiveCharacterTextSplitter({
    // 一段文本依照1000的巨细去拆分
    chunkSize: 1000,
    // 当前一段文本与上一段文本堆叠的巨细为200
    chunkOverlap: 200
});
// 2.3 切分数据
const docs = await splitter.splitDocuments(rawDocs);
// 打印
console.log(docs);

然后经过如下指令进行验证:

cd langchain-demo/
node ingest-data.js

成功成果如图所示:对比之前多了一个 loc: [Object]

基于自定义数据源的LangChain的聊天

接入向量数据库

这儿挑选的向量数据库是:pinecone 详细可参考官网文档自行挑选:

python.langchain.com/docs/get_st…

基于自定义数据源的LangChain的聊天
根据官网装置手册进行装置

python.langchain.com/docs/module…

基于自定义数据源的LangChain的聊天

pip install pinecone-client openai tiktoken
# dotenv用来读取环境变量 装置向量数据库
pnpm install -S dotenv langchain @pinecone-database/pinecone

将数据写入向量数据库

这儿选用的是Pinecone向量数据库。 首先咱们要注册一个Pinecone的数据库。官网地址:

www.pinecone.io/

注册完结后咱们需求创立一个Index,如图所示操作:

基于自定义数据源的LangChain的聊天
基于自定义数据源的LangChain的聊天

留意文中的数字1536不要写错。

一起咱们要记住自己创立的Index Name并找到,API Key,以及environment� 记下来,后边会用到。

基于自定义数据源的LangChain的聊天
完结上述操作后 接下来持续修正ingest-data.js文件,如下所示:

// 1. 读取markdown文件
import { UnstructuredLoader } from "langchain/document_loaders/fs/unstructured";
// 2. 文档拆分,将文档拆分红一块一块的
// 2.1 导入 langchain 提供的拆分东西
import { RecursiveCharacterTextSplitter } from "langchain/text_splitter";
// 运用这个将数据放入向量数据库里边
import { PineconeStore } from "langchain/vectorstores/pinecone"
import { OpenAIEmbeddings } from "langchain/embeddings/openai"
// 3. 导入向量数据库
import { PineconeClient } from "@pinecone-database/pinecone";
// 读取环境变量
import dotenv from "dotenv";
dotenv.config();
// 1.1 实例化UnstructuredLoader  并传入数据的途径
const unstructuredLoader = new UnstructuredLoader("./vue3-document.md");
// 1.2 读取文件,这是个promise 运用await
const rawDocs = await unstructuredLoader.load();
// 1.3
//console.log(rawDocs);
// 2.2 实例化 RecursiveCharacterTextSplitter
const splitter = new RecursiveCharacterTextSplitter({
    // 一段文本依照1000的巨细去拆分
    chunkSize: 1000,
    // 当前一段文本与上一段文本堆叠的巨细为200
    chunkOverlap: 200
});
// 2.3 切分数据
const docs = await splitter.splitDocuments(rawDocs);
// 打印
//console.log(docs);
// 3.1 初始化 pinecone
const pineconeClient = new PineconeClient();
await pineconeClient.init({
    apiKey: process.env.PINECONE_API_KEY,
    environment: process.env.PINECONE_ENV,
});
const pineconeIndex = pineconeClient.Index(process.env.PINECONE_INDEX);
try {
    PineconeStore.fromDocuments(docs, new OpenAIEmbeddings(),{
        // 向量数据库的信息
        pineconeIndex,
        textKey: "text",
        namespace: "teach-vue3-document",
    });
}catch (e) {
    console.log(e)
}

一起在项目根目录下创立一个.env文件,文件内容如下:

OPENAI_API_KEY="your openai key"
PINECONE_API_KEY="pinecone api key"
PINECONE_ENV="environment"
PINECONE_INDEX="index name"

完结上述操作后,执行如下指令:

cd langchain-demo/
node ingest-data.js

运转成功成果如图所示:

基于自定义数据源的LangChain的聊天
基于自定义数据源的LangChain的聊天
经过Pinecone的控制台咱们能够看到,文档数据现已成功的写入到了向量数据库中。

构建chains

创立一个chain.js,内容如下:

import { ConversationalRetrievalQAChain } from "langchain/chains";
// 导入大言语模型
import {OpenAI} from "langchain/llms/openai"
import { PineconeClient } from "@pinecone-database/pinecone";
import { PineconeStore } from "langchain/vectorstores/pinecone"
import { OpenAIEmbeddings } from "langchain/embeddings/openai"
// 读取环境变量
import dotenv from "dotenv";
dotenv.config();
// 创立大言语模型
const model = new OpenAI({
    // 准确度,越小越精准,越大越具有创造性
    temperature: 0,
});
// 创立向量数据库
const pineconeClient = new PineconeClient();
await pineconeClient.init({
    apiKey: process.env.PINECONE_API_KEY,
    environment: process.env.PINECONE_ENV,
});
const pineconeIndex = pineconeClient.Index(process.env.PINECONE_INDEX);
const pineconeStore = await PineconeStore.fromExistingIndex(new OpenAIEmbeddings(), {
    // 向量数据库的信息
    pineconeIndex,
    textKey: "text",
    namespace: "teach-vue3-document",
});
const chain = ConversationalRetrievalQAChain.fromLLM(
    model,
    pineconeStore.asRetriever(),{
        // 回来信息是参考了什么资料的开关 sourceDocuments:
        returnSourceDocuments: true,
    });
const res = await chain.call({
    question: "vue3 如何为为 reactive() 标示类型  请给我写一个demo",
    // 谈天前史,也便是回忆的功用
    chat_history: [],
});
console.log(res);
// langchain 0.90版本这样写有问题,详细可参考:
// const secondRes = await chain.call({
//     question: "能否提供更多的demo",
//     // 谈天前史,也便是回忆的功用
//     chat_history: [
//         "vue3 如何为 ref() 标示类型 请给我写一个demo",
//         res.text
//     ],
// });
console.log(secondRes);

完结上述操作后,执行如下指令:

cd langchain-demo/
node ingest-data.js

运转成果如下:

基于自定义数据源的LangChain的聊天
其实我个人认为这个成果不如人意,可是至少这样做的方向是正确的。

构建后端

  1. 运用koa-setup构建后端
# 装置koa-setup
npm install -g koa-setup
koa-setup

如图:

基于自定义数据源的LangChain的聊天

  1. 然后修正生成的server文件夹中的package.json文件中的type为module。并增加**”dev”: “nodemon index.js”�**如图:

基于自定义数据源的LangChain的聊天

  1. 修正server文件夹下的index.js文件,如下:

import Koa from "koa"
import Router from "koa-router"
import { koaBody } from "koa-body";
// const Koa = require("koa")
// const Router = require("koa-router")
// const koaBody = require("koa-body")
const app = new Koa()
app.use(koaBody({
    multipart:true
}))
const router = new Router()
router.get("/",(ctx)=>{
    ctx.body = "hello server"
})
app.use(router.routes())
app.listen(8080,()=>{
    console.log("open server localhost:8080")
})
  1. 装置nodemon
cd server/
pnpm i nodemon -D

nodemon类似于热布置,修正代码无需重新发动。

基于自定义数据源的LangChain的聊天

  1. 发动项目
pnpm dev

发动成功:

基于自定义数据源的LangChain的聊天
基于自定义数据源的LangChain的聊天

构建API

chat.js ingest-data.js vue3-document.md .env文件移动到server文件夹下,如图:

基于自定义数据源的LangChain的聊天
然后修正index.js和chat.js,概况如下: index.js

import Koa from "koa"
import Router from "koa-router"
import { koaBody } from "koa-body";
import { chat } from "./chain.js";
// const Koa = require("koa")
// const Router = require("koa-router")
// const koaBody = require("koa-body")
const app = new Koa()
app.use(koaBody({
    multipart:true
}))
const router = new Router()
router.get("/",(ctx)=>{
    ctx.body = "hello server"
})
// 编写接口
router.post("/chat",async (ctx) => {
    const { message } = ctx.request.body;
    const result  = await chat(message)
    ctx.body = {
        data: result,
        state: 1,
    }
})
app.use(router.routes())
app.listen(8080,()=>{
    console.log("open server localhost:8080")
})

�chat.js

import { ConversationalRetrievalQAChain } from "langchain/chains";
// 导入大言语模型
import {OpenAI} from "langchain/llms/openai"
import { PineconeClient } from "@pinecone-database/pinecone";
import { PineconeStore } from "langchain/vectorstores/pinecone"
import { OpenAIEmbeddings } from "langchain/embeddings/openai"
// 读取环境变量
import dotenv from "dotenv";
dotenv.config();
// 创立大言语模型
const model = new OpenAI({
    // 准确度,越小越精准,越大越具有创造性
    temperature: 0,
});
// 创立向量数据库
const pineconeClient = new PineconeClient();
await pineconeClient.init({
    apiKey: process.env.PINECONE_API_KEY,
    environment: process.env.PINECONE_ENV,
});
const pineconeIndex = pineconeClient.Index(process.env.PINECONE_INDEX);
const pineconeStore = await PineconeStore.fromExistingIndex(new OpenAIEmbeddings(), {
    // 向量数据库的信息
    pineconeIndex,
    textKey: "text",
    namespace: "teach-vue3-document",
});
const chain = ConversationalRetrievalQAChain.fromLLM(
    model,
    pineconeStore.asRetriever(),{
        // 回来信息是参考了什么资料的开关 sourceDocuments:
        returnSourceDocuments: true,
    });
export async function chat(message) {
    const res = await chain.call({
        question: message,
        // 谈天前史,也便是回忆的功用
        chat_history: [],
    });
    return res;
}

然后发动运转pnpm dev并运用postman访问接口 “/chat” 如图:

构建前端

pnpm create vite

基于自定义数据源的LangChain的聊天
装置组件tailwindcss

cd client/
pnpm install -D tailwindcss@latest postcss@latest autoprefixer@latest

# 执行init
npx tailwindcss init -p

# 装置axios 后续运用
pnpm i axios

# 装置 marked marked 是一个盛行的 JavaScript 库,用于将 Markdown 文本转化为 HTML
pnpm install marked
pnpm install --save-dev @types/marked
pnpm install typescript --save-dev

tailwind.config.js增加装备(参考官网:v2.tailwindcss.com/docs/guides…)

purge: ["./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}"],

修正style.css 文件(参考官网:v2.tailwindcss.com/docs/guides…)

@tailwind base;
@tailwind components;
@tailwind utilities;

然后在App.vue中编写Hello World。

<script setup>
</script>
<template>
  <div class="text-blue-400">
    Hello World
  </div>
</template>
<style scoped>
</style>

发动

cd client/
pnpm dev

页面如下:

基于自定义数据源的LangChain的聊天
接下来编写视图,(前端组件、js等) viteproxy文档:cn.vitejs.dev/config/serv…

源码获取:微信查找【码上遇见你】回复【langchain-demo】

上述文章也是根据网络整理的。侵权删之。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。