项目开发整体流程
数据准备 → 数据向量化 → 机器人实现 → 界面部署 → 主流程
- 数据准备:生成心理咨询问题和答案的数据,并将这些数据保存到文件data.txt中。
- 数据向量化:利用langchain_text_splitters库的CharacterTextSplitter模块对数据进行预处理,然后使用智谱AI的向量模型进行向量化,并将向量数据存储在FAISS向量数据库中。
- 机器人实现:定义一个聊天机器人,通过加载FAISS向量数据库,利用检索器获取相关问题,并结合上下文和对话历史生成回复。这里使用ChatZhipuAI作为聊天模型。
- 界面部署:使用Gradio库创建用户界面,用户可以通过该界面与聊天机器人进行交流。
- 主流程:在程序入口处,首先调用函数初始化聊天机器人,然后调用Gradio界面,完成整个心理咨询机器人的搭建。
数据向量化
数据准备
首先我们需要一些通用的数据,因为我不是心理咨询师,作为开发者我需要一些资料------关于心理咨询会遇到的问题和对应的答案。
可以直接让智谱清言为我们生成一些心理咨询相关的问题和答案,先生成50条吧。
虽然智谱清言说"很抱歉",但还是为我们生成了10条问答。那就让他继续吧,直到输出50条为止。
把这些数据复制到文件data.txt中。
在做向量化之前,需要先对数据进行预处理。可以用langchain_text_splitters库的CharacterTextSplitter,langchain提供了多种工具用于处理文档,CharacterTextSplitter模块主要用于拆分文本字符。
python
from langchain_text_splitters import CharacterTextSplitter
with open("data.txt") as f:
data = f.read()
text_splitter = CharacterTextSplitter(
separator="\n",
chunk_size=200,
length_function=len,
is_separator_regex=True,
)
docs = text_splitter.create_documents([data])
- separator被设置为\n,这表示文本将会以换行符作为分隔符进行分割。
- chunk_size 被设置为200,这表示每个文本块的大小为200个字符。
- length_function 被设置为len,这表示用于计算文本长度的函数为Python内置的len函数。
- is_separator_regex 被设置为True,这表示分隔符会被视为一个正则表达式进行处理。
向量数据库的创建
接下来将处理好的数据向量化,可以用FAISS(FaceBook开源的向量数据库)进行管理:
python
from langchain_community.vectorstores.faiss import FAISS
from langchain_zhipu.embeddings import ZhipuAIEmbeddings
from utils import get_ak
db = FAISS.from_documents(docs, ZhipuAIEmbeddings(
api_key=get_ak(),
))
首先,引入这个ZhipuAIEmbeddings模块代表我们使用了智谱的向量模型进行向量化。langchain_zhipu这个库不是官方的,因为智谱AI的官方SDK使用了 pydantic v2,这与 langchain(尤其是langserve)不兼容,所以有人写了这个库langchain_zhipu对智谱和langchain的库进行适配。
get_ak()是我写的一个方法,只是return我的api_key。没有api_key的话可以去智谱AI开发平台注册获取。
langchain_community.vectorstores.faiss库引入了向量数据库FAISS,langchain_community是LangChain社区包含的第三方集成。from_documents方法用于通过文档和嵌入来初始化VectorStore(VectorStore是一个抽象基类,用于表示向量存储)。
查询与检索
python
docs = db.similarity_search("物业管理怎么样?",k=3)
async def asimilarity():
results = await db.asimilarity_search("我的同事批评我怎么办?", k=3)
asyncio.run(asimilarity())
db.save_local("faiss_index")
db.similarity_search("物业管理怎么样?", k=3) - 这一行代码是在数据库db中进行相似性搜索,使用输入的查询字符串"物业管理怎么样?"来查找相似的文档,k=3表示向量数据库将查找前3相似的文本。db.asimilarity_search是相同的功能,不过是异步的实现。
最后,使用db对象的save_local方法将Faiss索引保存在本地文件"faiss_index"中。
需要注意的是向量化的过程会消耗大量时间,这个例子中的data.txt向量化完成需要90秒左右。
机器人实现
机器人初始化
python
def initialize_chatbot(vector_store_dir: str="faiss_index"):
db = FAISS.load_local(vector_store_dir, ZhipuAIEmbeddings(api_key=get_ak()), allow_dangerous_deserialization=True)
llm = ChatZhipuAI(model_name="glm-4", temperature=0.8, api_key=get_ak())
template = """
Use the following context (delimited by <ctx></ctx>) and the chat history (delimited by <hs></hs>) to answer the question:
------
<ctx>
{context}
</ctx>
------
<hs>
{history}
</hs>
------
{question}
"""
prompt = PromptTemplate(
input_variables=["history", "context", "question"],
template=template,
)
global BOT
BOT = RetrievalQA.from_chain_type(
llm,
retriever=db.as_retriever(search_kwargs={"k": 1}),
chain_type='stuff',
chain_type_kwargs={
"verbose": True,
"prompt": prompt,
"memory": ConversationBufferMemory(
memory_key="history",
input_key="question"
),
}
)
# 返回向量数据库的检索结果
BOT.return_source_documents = True
return BOT
这段代码通过initialize_chatbot函数初始化一个聊天机器人。
首先,它加载了本地的向量存储vector_store_dir,并使用ZhipuAI嵌入的API密钥来获取数据库db。然后,实例化了一个ChatZhipuAI模型llm,使用指定的模型名称和API密钥。其中的参数temperature用于指定语言模型生成文本时的多样性或不确定性的程度,较高的temperature值会导致更加多样化和不确定的输出,而较低的值则倾向于生成更加确定性和保守的输出。
接下来,定义了一个模板template,用于指定如何使用上下文、对话历史和问题来回答问题。langchain_core.prompts库的PromptTemplate模块用于存储模版。
随后,在全局命名空间中创建了一个名为BOT的RetrievalQA实例。这里使用RetrievalQA.from_chain_type方法,传入llm作为聊天模型,db作为检索器,并传入各种其他参数和设置来配置聊天过程。最后,代码设置了BOT.return_source_documents为True,以便返回向量数据库的检索结果。
Gradio界面部署
python
def chat(message, history):
ans = BOT({"query": message})
print(ans)
return ans["result"]
def launch_gradio():
demo = gr.ChatInterface(
fn=chat,
title="心理咨询",
chatbot=gr.Chatbot(height=600),
)
demo.launch(share=True, server_name="0.0.0.0")
if __name__ == "__main__":
initialize_chatbot()
launch_gradio()
launch_gradio函数创建了一个基于Gradio库的用户界面,用于展示心理咨询的聊天机器人。
最后,在程序的主入口点处,initialize_chatbot函数用于初始化聊天机器人,然后调用launch_gradio函数,启动了Gradio用户界面,从而允许用户与聊天机器人进行交互。