From 50a6e2d4400b3678d7d5aa4587589e5b304a4b7d Mon Sep 17 00:00:00 2001 From: liukl <1138493417@qq.com> Date: Fri, 7 Jul 2023 12:40:13 +0800 Subject: [PATCH 1/4] wechaty with langchain --- jekyll/_contributors/bestk.md | 13 ++ .../2023-07-07-wechaty-chat-with-langchain.md | 165 ++++++++++++++++++ .../image1.webp | Bin 0 -> 10066 bytes .../07-wechaty-chat-with-langchain/logo.webp | Bin 0 -> 7162 bytes jekyll/assets/contributors/bestk/avatar.webp | Bin 0 -> 10758 bytes 5 files changed, 178 insertions(+) create mode 100644 jekyll/_contributors/bestk.md create mode 100644 jekyll/_posts/2023-07-07-wechaty-chat-with-langchain.md create mode 100644 jekyll/assets/2023/07-wechaty-chat-with-langchain/image1.webp create mode 100644 jekyll/assets/2023/07-wechaty-chat-with-langchain/logo.webp create mode 100644 jekyll/assets/contributors/bestk/avatar.webp diff --git a/jekyll/_contributors/bestk.md b/jekyll/_contributors/bestk.md new file mode 100644 index 000000000..52dc7dd9c --- /dev/null +++ b/jekyll/_contributors/bestk.md @@ -0,0 +1,13 @@ +--- +name: bestk +site: https://github.com/bestk +avatar: /assets/contributors/bestk/avatar.webp +bio: java/node/python/golang +twitter: +--- + +普适程序员 + +## Contact me + +- Github: diff --git a/jekyll/_posts/2023-07-07-wechaty-chat-with-langchain.md b/jekyll/_posts/2023-07-07-wechaty-chat-with-langchain.md new file mode 100644 index 000000000..098b6f45b --- /dev/null +++ b/jekyll/_posts/2023-07-07-wechaty-chat-with-langchain.md @@ -0,0 +1,165 @@ +--- +title: "使用 wechaty langchain 部署私有 chatgpt" +author: bestk +categories: article +tags: + - chatgpt + - langchain +image: /assets/2023/07-wechaty-chat-with-langchain/logo.webp +--- + + +WeChaty 是一个基于 Node.js 的开源微信机器人框架,而 LangChain 是一个用于部署私有化 GPT 模型的工具。通过结合 WeChaty 和 LangChain,你可以创建一个私有化的 GPT 机器人,使其在微信平台上运行。 + +Setup: + +我们使用 `wechaty-puppet-wechat4u` + +```Text +package.json: +"wechaty": "^1.20.2", +"wechaty-puppet-wechat4u": "1.14.1" +"langchain": "^0.0.102", +"@pinecone-database/pinecone": "^0.1.6", +"pdf-parse": "^1.1.1", // 篇幅原因这里只演示 pdf +``` + +```javascript +import { WechatyBuilder} from 'wechaty' + +const wechaty = WechatyBuilder.build({ + name: 'wechaty-chatgpt', + puppet: 'wechaty-puppet-wechat4u', + puppetOptions: { + uos: true, + }, +}); + +``` + +设置 pinecone ,openai + +```bash +PROMPTLAYER_API_KEY=pl_... # PROMPTLAYER 是一个用于记录 api 调用时 prompt 与 response 的工具 +PINECONE_API_KEY=89e... +PINECONE_ENVIRONMENT=us-west4-gcp-free +PINECONE_INDEX=... +``` + + +以下代码为当接收到支持的文件对文件进行向量化成功后返回提示 + ```javascript + wechaty.on('message', async message => { + const contact = message.talker(); + currentAdminUser = contact.payload.alias === process.env.ADMIN + const receiver = message.listener(); + let content = message.text().trim(); + const room = message.room(); + const target = room || contact; + const isText = message.type() === wechaty.Message.Type.Text; + const isAudio = message.type() === wechaty.Message.Type.Audio; + const isFile = message.type() === wechaty.Message.Type.Attachment; + + if (isFile) { + const filebox = await message.toFileBox() + if (supportFileType(filebox.mediaType)) { + await saveFile(filebox) + await loadDocuments() + await send(room || contact, `${filebox.name} Embeddings 成功`) + return + } + } + }) + ``` + ![image1.webp](/assets/2023/07-wechaty-chat-with-langchain/image1.webp) + +### langchain 相关代码 +```javascript +import { PineconeClient } from "@pinecone-database/pinecone"; +import dotenv from 'dotenv'; +import { VectorDBQAChain } from "langchain/chains"; +import { DirectoryLoader } from "langchain/document_loaders"; +import { DocxLoader } from "langchain/document_loaders/fs/docx"; +import { PDFLoader } from "langchain/document_loaders/fs/pdf"; +import { TextLoader } from "langchain/document_loaders/fs/text"; +import { OpenAIEmbeddings } from "langchain/embeddings/openai"; +import { PromptLayerOpenAI } from "langchain/llms/openai"; +import { RecursiveCharacterTextSplitter } from "langchain/text_splitter"; +import { PineconeStore } from "langchain/vectorstores"; + +dotenv.config(); +const client = new PineconeClient(); + +await client.init({ + apiKey: process.env.PINECONE_API_KEY, + environment: process.env.PINECONE_ENVIRONMENT, +}); + +const pineconeIndex = client.Index(process.env.PINECONE_INDEX); + + +async function loadDocuments(directory = 'resource') { + console.log('loadDocuments...') + const loader = new DirectoryLoader(directory, + { + ".pdf": (path) => new PDFLoader(path), + ".txt": (path) => new TextLoader(path), + ".doc": (path) => new DocxLoader(path), + ".docx": (path) => new DocxLoader(path), + }); + // 将数据转成 document 对象,每个文件会作为一个 document + const rawDocuments = await loader.load(); + console.log(`documents: ${rawDocuments.length}`); + + // 初始化加载器 + const textSplitter = new RecursiveCharacterTextSplitter({ chunkSize: 500 }); + // 切割加载的 document + const splitDocs = await textSplitter.splitDocuments(rawDocuments); + + // 持久化数据 + // const docsearch = await Chroma.fromDocuments(splitDocs, embeddings, { collectionName: "private_doc" }); + // docsearch.persist(); + + + await PineconeStore.fromDocuments(splitDocs, new OpenAIEmbeddings(), { + pineconeIndex, + }); + console.log(`send to PineconeStore`); + +} + + +async function askDocument(question) { + const llm = new PromptLayerOpenAI({ plTags: ["langchain-requests", "chatbot"] }) + // 初始化 openai 的 embeddings 对象 + + // 加载数据 + const vectorStore = await PineconeStore.fromExistingIndex( + new OpenAIEmbeddings(), + { pineconeIndex } + ); + + /* Search the vector DB independently with meta filters */ + const chain = VectorDBQAChain.fromLLM(llm, vectorStore, { + k: 1, + returnSourceDocuments: true, + }); + const response = await chain.call({ query: question }); + console.log(response); + + // const response = await vectorStore.similaritySearch(question, 1); + // console.log(response); + + return response.text +} + +function supportFileType(mediaType) { + const types = ['doc', 'docx', , 'pdf', 'text'] + return types.filter(e => mediaType.includes(e)).length > 0 +} + + +export { askDocument, loadDocuments, supportFileType }; + + +``` diff --git a/jekyll/assets/2023/07-wechaty-chat-with-langchain/image1.webp b/jekyll/assets/2023/07-wechaty-chat-with-langchain/image1.webp new file mode 100644 index 0000000000000000000000000000000000000000..69384306cc4b242315fb6200874c9199af273b5f GIT binary patch literal 10066 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 UPTv;C^hNeWqINytzgGSK0JpZaTL1t6 literal 0 HcmV?d00001 diff --git a/jekyll/assets/2023/07-wechaty-chat-with-langchain/logo.webp b/jekyll/assets/2023/07-wechaty-chat-with-langchain/logo.webp new file mode 100644 index 0000000000000000000000000000000000000000..2790b759c5ee8e7b2a729878e4b2e9814e69c2c6 GIT binary patch literal 7162 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 literal 0 HcmV?d00001 diff --git a/jekyll/assets/contributors/bestk/avatar.webp b/jekyll/assets/contributors/bestk/avatar.webp new file mode 100644 index 0000000000000000000000000000000000000000..80f8c991c418bed851a8937e8cb0446642549422 GIT binary patch literal 10758 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 Date: Fri, 7 Jul 2023 07:26:52 +0000 Subject: [PATCH 2/4] wechaty with langchain --- .../2023-07-07-wechaty-chat-with-langchain.md | 180 +++++++++--------- 1 file changed, 90 insertions(+), 90 deletions(-) diff --git a/jekyll/_posts/2023-07-07-wechaty-chat-with-langchain.md b/jekyll/_posts/2023-07-07-wechaty-chat-with-langchain.md index 098b6f45b..ef7cee444 100644 --- a/jekyll/_posts/2023-07-07-wechaty-chat-with-langchain.md +++ b/jekyll/_posts/2023-07-07-wechaty-chat-with-langchain.md @@ -46,8 +46,8 @@ PINECONE_ENVIRONMENT=us-west4-gcp-free PINECONE_INDEX=... ``` - 以下代码为当接收到支持的文件对文件进行向量化成功后返回提示 + ```javascript wechaty.on('message', async message => { const contact = message.talker(); @@ -71,95 +71,95 @@ PINECONE_INDEX=... } }) ``` - ![image1.webp](/assets/2023/07-wechaty-chat-with-langchain/image1.webp) - -### langchain 相关代码 -```javascript -import { PineconeClient } from "@pinecone-database/pinecone"; -import dotenv from 'dotenv'; -import { VectorDBQAChain } from "langchain/chains"; -import { DirectoryLoader } from "langchain/document_loaders"; -import { DocxLoader } from "langchain/document_loaders/fs/docx"; -import { PDFLoader } from "langchain/document_loaders/fs/pdf"; -import { TextLoader } from "langchain/document_loaders/fs/text"; -import { OpenAIEmbeddings } from "langchain/embeddings/openai"; -import { PromptLayerOpenAI } from "langchain/llms/openai"; -import { RecursiveCharacterTextSplitter } from "langchain/text_splitter"; -import { PineconeStore } from "langchain/vectorstores"; - -dotenv.config(); -const client = new PineconeClient(); - -await client.init({ - apiKey: process.env.PINECONE_API_KEY, - environment: process.env.PINECONE_ENVIRONMENT, -}); - -const pineconeIndex = client.Index(process.env.PINECONE_INDEX); - - -async function loadDocuments(directory = 'resource') { - console.log('loadDocuments...') - const loader = new DirectoryLoader(directory, - { - ".pdf": (path) => new PDFLoader(path), - ".txt": (path) => new TextLoader(path), - ".doc": (path) => new DocxLoader(path), - ".docx": (path) => new DocxLoader(path), - }); - // 将数据转成 document 对象,每个文件会作为一个 document - const rawDocuments = await loader.load(); - console.log(`documents: ${rawDocuments.length}`); - - // 初始化加载器 - const textSplitter = new RecursiveCharacterTextSplitter({ chunkSize: 500 }); - // 切割加载的 document - const splitDocs = await textSplitter.splitDocuments(rawDocuments); - - // 持久化数据 - // const docsearch = await Chroma.fromDocuments(splitDocs, embeddings, { collectionName: "private_doc" }); - // docsearch.persist(); - - - await PineconeStore.fromDocuments(splitDocs, new OpenAIEmbeddings(), { - pineconeIndex, - }); - console.log(`send to PineconeStore`); -} +![image1.webp](/assets/2023/07-wechaty-chat-with-langchain/image1.webp) +langchain 相关代码 -async function askDocument(question) { - const llm = new PromptLayerOpenAI({ plTags: ["langchain-requests", "chatbot"] }) - // 初始化 openai 的 embeddings 对象 - - // 加载数据 - const vectorStore = await PineconeStore.fromExistingIndex( - new OpenAIEmbeddings(), - { pineconeIndex } - ); - - /* Search the vector DB independently with meta filters */ - const chain = VectorDBQAChain.fromLLM(llm, vectorStore, { - k: 1, - returnSourceDocuments: true, - }); - const response = await chain.call({ query: question }); - console.log(response); - - // const response = await vectorStore.similaritySearch(question, 1); - // console.log(response); - - return response.text -} - -function supportFileType(mediaType) { - const types = ['doc', 'docx', , 'pdf', 'text'] - return types.filter(e => mediaType.includes(e)).length > 0 -} - - -export { askDocument, loadDocuments, supportFileType }; - - -``` + ```javascript + import { PineconeClient } from "@pinecone-database/pinecone"; + import dotenv from 'dotenv'; + import { VectorDBQAChain } from "langchain/chains"; + import { DirectoryLoader } from "langchain/document_loaders"; + import { DocxLoader } from "langchain/document_loaders/fs/docx"; + import { PDFLoader } from "langchain/document_loaders/fs/pdf"; + import { TextLoader } from "langchain/document_loaders/fs/text"; + import { OpenAIEmbeddings } from "langchain/embeddings/openai"; + import { PromptLayerOpenAI } from "langchain/llms/openai"; + import { RecursiveCharacterTextSplitter } from "langchain/text_splitter"; + import { PineconeStore } from "langchain/vectorstores"; + + dotenv.config(); + const client = new PineconeClient(); + + await client.init({ + apiKey: process.env.PINECONE_API_KEY, + environment: process.env.PINECONE_ENVIRONMENT, + }); + + const pineconeIndex = client.Index(process.env.PINECONE_INDEX); + + + async function loadDocuments(directory = 'resource') { + console.log('loadDocuments...') + const loader = new DirectoryLoader(directory, + { + ".pdf": (path) => new PDFLoader(path), + ".txt": (path) => new TextLoader(path), + ".doc": (path) => new DocxLoader(path), + ".docx": (path) => new DocxLoader(path), + }); + // 将数据转成 document 对象,每个文件会作为一个 document + const rawDocuments = await loader.load(); + console.log(`documents: ${rawDocuments.length}`); + + // 初始化加载器 + const textSplitter = new RecursiveCharacterTextSplitter({ chunkSize: 500 }); + // 切割加载的 document + const splitDocs = await textSplitter.splitDocuments(rawDocuments); + + // 持久化数据 + // const docsearch = await Chroma.fromDocuments(splitDocs, embeddings, { collectionName: "private_doc" }); + // docsearch.persist(); + + + await PineconeStore.fromDocuments(splitDocs, new OpenAIEmbeddings(), { + pineconeIndex, + }); + console.log(`send to PineconeStore`); + + } + + + async function askDocument(question) { + const llm = new PromptLayerOpenAI({ plTags: ["langchain-requests", "chatbot"] }) + // 初始化 openai 的 embeddings 对象 + + // 加载数据 + const vectorStore = await PineconeStore.fromExistingIndex( + new OpenAIEmbeddings(), + { pineconeIndex } + ); + + /* Search the vector DB independently with meta filters */ + const chain = VectorDBQAChain.fromLLM(llm, vectorStore, { + k: 1, + returnSourceDocuments: true, + }); + const response = await chain.call({ query: question }); + console.log(response); + + // const response = await vectorStore.similaritySearch(question, 1); + // console.log(response); + + return response.text + } + + function supportFileType(mediaType) { + const types = ['doc', 'docx', , 'pdf', 'text'] + return types.filter(e => mediaType.includes(e)).length > 0 + } + + + export { askDocument, loadDocuments, supportFileType }; + ``` From 2ce2d6c380ea7f74800e4459a5922156b4f6add5 Mon Sep 17 00:00:00 2001 From: ECH2O <1138493417@qq.com> Date: Fri, 7 Jul 2023 07:27:03 +0000 Subject: [PATCH 3/4] 0.11.48 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 35ae13c42..93b4f6a52 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty-jekyll", - "version": "0.11.47", + "version": "0.11.48", "description": "Wechaty Official Website for News, Blogs, Contributor Profiles", "private": true, "type": "module", From 63fa135b3aca701d7ed845664584a399e681dd44 Mon Sep 17 00:00:00 2001 From: ECH2O <1138493417@qq.com> Date: Fri, 7 Jul 2023 07:27:47 +0000 Subject: [PATCH 4/4] 0.11.49 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 93b4f6a52..074a33309 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty-jekyll", - "version": "0.11.48", + "version": "0.11.49", "description": "Wechaty Official Website for News, Blogs, Contributor Profiles", "private": true, "type": "module",