免费建立本地AI聊天机器人 - 免费
#javascript #网络开发人员 #python #ai

蹲式老虎,隐藏的龙

  • 这一切始于对PrivateGPT的好奇心。
  • 但是,在挖掘一点之后,真实的MVP是LangChain
  • 这是我的“创建本地AI聊天机器人的旅程”的快速摘要,希望能节省人们的痛苦。

(第1部分)设置

(1A)要求

(1B)虚拟环境与模块

  • 创建一个项目文件夹。例如。 D:\CHATBOT
  • 打开终端,然后导航到项目文件夹cd D:\CHATBOT
  • 创建虚拟环境virtualenv venv
  • 激活IT venv\Scripts\activate(Windows),venv/bin/activate(Mac/Linux)。
  • pip install gpt4all chromadb langchain bs4

(1C)GPT4ALL模型

  • 访问GPT4All Website,向下滚动到“模型Explorer”。
  • 选择你的毒药。将您选择的模型保存到D:\CHATBOT\models中。

(第2部分)上下文和设置

(2a)虚拟文件

2a-dummy.txt

John is 12 years old, and wears a blue polo shirt.
His favorite color is blue, and likes to dance.
When he grows up, his dream is to be a farmer.
  • 在进入“实际代码”之前,我们要处理“不是那么编程”的零件。
  • 这只是一个虚拟文档,用作上下文。

(2B)提示模板

2b-prompt.txt

Use the following context section and only that context to answer the question at the end.
Do not use your internal knowledge. If you don't know the answer, just say that you don't know, don't try to make up an answer.

Context: {context}
Question: {query}
Answer:
  • 简单地说,我们使用它来修改用户的原始问题。
  • 用户的问题将插入{query}
  • 上述虚拟文档的相关部分将插入为{context},因此AI知道发生了什么。

(2C)设置

2c-settings.json

{
  "model_file" : "ggml-model-gpt4all-falcon-q4_0.bin",
  "model_tokens" : 1000,
  "doc_file" : "2a-dummy.txt",
  "doc_chunks" : 512,
  "doc_overlap" : 20,
  "ws_host" : "localhost",
  "ws_port" : 5678
}

model_file更改为自己。

(第3部分)命令行聊天机器人

3-cli.py

# (A) LOAD MODULES
import os, json
from langchain.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.vectorstores import Chroma
from langchain.embeddings import GPT4AllEmbeddings
from langchain.llms import GPT4All
from langchain import PromptTemplate, LLMChain

# (B) SETTINGS
# (B1) SYSTEM PATH
set = { "path" : os.path.dirname(os.path.realpath(__file__)) }

# (B2) LOAD SETTINGS
with open(os.path.join(set["path"], "2c-settings.json"), "r") as fs:
  set.update(json.load(fs))
  fs.close()
  set["model_file"] = os.path.join(set["path"], "models", set["model_file"])
  set["doc_file"] = os.path.join(set["path"], set["doc_file"])

# (B3) LOAD PROMPT TEMPLATE
with open(os.path.join(set["path"], "2b-prompt.txt"), "r") as fs:
  set["prompt"] = fs.read()
  fs.close()

# (C) INIT
# (C1) CREATE VECTOR STORE FROM DOCUMENT
vstore = Chroma.from_documents(
  documents = RecursiveCharacterTextSplitter(
    chunk_size = set["doc_chunks"], chunk_overlap = set["doc_overlap"]
  ).split_documents(TextLoader(set["doc_file"]).load()),
  embedding = GPT4AllEmbeddings()
)

# (C2) LLM
llm = GPT4All(model = set["model_file"], max_tokens = set["model_tokens"])

# (D) Q&A SESSION
while True:
  # (D1) LISTEN TO QUERIES
  query = input("\nEnter a query: ")
  if query == "exit":
    break
  if query.strip() == "":
    continue

  # (D2) BUILD CONTEXT FROM QUERY & VECTOR STORE
  context = ""
  for doc in vstore.similarity_search(query):
    context = context + doc.page_content + " \n\n "

  # (D3) LLM CHAIN
  llm_chain = LLMChain(
    llm = llm,
    prompt = PromptTemplate(
      template = set["prompt"], input_variables = ["context", "query"]
    ).partial(context = context)
  )

   # (D4) OUTPUT RESULT
  print(llm_chain.run(query))

CLI Chatbot

  • (a)加载所需的模块。
  • (b)加载设置和提示模板。
  • (C1)基于2-dummy.txt创建一个矢量存储(数据库)。
  • (C2)“使用GPT4All”作为LLM(大语言模型)。
  • (d)无尽回答问题的循环。
    • (d1)听query输入。
    • (d2)基于query,从vector Store中提取数据的恢复部分为context
    • (d3)将查询,上下文,提示模板馈入模型。
    • (D4)输出结果。

(第4部分)基于Web的聊天机器人

(4A)Websocket模块

  • 聊天机器人已经有效。
  • 但是,如果您想“实施到网页”,最简单的方法是使用WebSockets。
  • pip install websockets

(4B)修改的聊天机器人脚本

4b-web.py

# A TO C ARE PRETTY MUCH THE SAME
# ONLY AN ADDITIONAL "IMPORT WEBSOCKETS"

# (D) Q&A SESSION
# (D1) ANSWER QUERY
async def qna (websocket):
  async for query in websocket:
    # (D1-1) BUILD CONTEXT FROM QUERY & VECTOR STORE
    context = ""
    for doc in vstore.similarity_search(query):
      context = context + doc.page_content + " \n\n "

    # (D1-2) LLM CHAIN
    llm_chain = LLMChain(
      llm = llm,
      prompt = PromptTemplate(
        template = set["prompt"], input_variables = ["context", "query"]
      ).partial(context = context)
    )

    # (D1-3) RESPOND
    await websocket.send(llm_chain.run(query))

# (D2) GO!
async def main ():
  async with websockets.serve(qna, set["ws_host"], set["ws_port"]):
    print("Server deployed at " + set["ws_host"] + ":" + str(set["ws_port"]))
    await asyncio.Future()

if __name__ == "__main__":
  asyncio.run(main())

几乎相同 - 除了我们现在将聊天机器人放在ws://localhost:5678的websocket后面。

(4C)聊天机器人HTML页面

4c-web.html

<!-- (A) CHAT HISTORY -->
<div id="messages"></div>

<!-- (B) QUESTION -->
<form id="question" onsubmit="return chat.send()">
  <input type="text" id="qTxt" placeholder="Question" required disabled>
  <input type="submit" id="qGo" value="Go" disabled>
</form>

Web AI Chatbot

  • <div id="messages">聊天历史。
  • <form id="question">输入您的问题。

(4D)聊天机器人JavaScript

4d-web.js

var chat = {
  // (A) SETTINGS & FLAGS
  host : "ws://localhost:5678/", socket : null,
  hMsg : null, hTxt : null, hGo : null,

  // (B) INIT
  init : () => {
    // (B1) GET HTML ELEMENTS
    chat.hMsg = document.getElementById("messages");
    chat.hTxt = document.getElementById("qTxt");
    chat.hGo = document.getElementById("qGo");

    // (B2) CONNECT TO WEBSOCKET
    chat.socket = new WebSocket(chat.host);

    // (B3) ON CONNECT - ENABLE QUERY FORM
    chat.socket.addEventListener("open", () => {
      chat.controls(1);
      chat.draw("Ready!", "sys");
    });

    // (B4) ON RECEIVE MESSAGE - DRAW IN HTML
    chat.socket.addEventListener("message", e => chat.draw(e.data, "bot"));

    // (B5) ON ERROR & CONNECTION LOST
    chat.socket.addEventListener("close", () => {
      chat.controls();
      chat.draw("Websocket connection lost!", "sys");
    });
    chat.socket.addEventListener("error", err => {
      chat.controls();
      console.log(err);
      chat.draw("Websocket connection error!", "sys");
    });
  },

  // (C) TOGGLE HTML CONTROLS
  controls : enable => {
    if (enable) {
      chat.hTxt.disabled = false;
      chat.hGo.disabled = false;
    } else {
      chat.hTxt.disabled = true;
      chat.hGo.disabled = true;
    }
  },

  // (D) SEND MESSAGE TO CHAT SERVER
  send : () => {
    chat.controls(); // disable question form until bot replies
    chat.draw(chat.hTxt.value, "human");
    chat.socket.send(chat.hTxt.value);
    chat.hTxt.value = "";
    return false;
  },

  // (E) DRAW MESSAGE IN HTML
  draw : (msg, css) => {
    let row = document.createElement("div");
    row.className = css;
    row.innerHTML = `<div class="chatName">${css}</div> <div class="chatMsg">${msg}</div>`;
    chat.hMsg.appendChild(row);
    if (css=="bot") { chat.controls(1); } // enable form on bot reply
    // window.scrollTo(0, 0);
  }
};
window.addEventListener("load", chat.init);

不要逐行解释...几乎是“连接到ws://localhost:5678”,发送问题并从AI ChatBot接收答案。

结束

这是要点上的代码的链接,还有其他一些内容: