RAG实操教程langchain+Milvus向量数据库创建你的本地知识库 二
Miluvs 向量数据库
关于Milvui可以参考我的前两篇文章
下面我们安装pymilvus库
pipinstall--upgrade--quietpymilvus
如果你使用的不是Miluvs数据库,那也没关系,langchain已经给我们分装了几十种向量数据库,你选择你需要的数据库即可。本文中我们是系列教程中一篇,所以我们使用Miluvs向量库。
Embedding model
这里需要明确的两个功能是:
我这里使用AzureOpenAIEmbeddings是个收费的模型。有开源的embedding Model可以部署在本地使用,如果你的机器性能足够好。如果要本地部署可以参考docker部署llama2模型 。
这里我使用AzureOpenAIEmbeddings, 相关配置我放到了.env文件中,并使用dotenv加载。
#AZUREconfig
AZURE_OPENAI_ENDPOINT=''
AZURE_OPENAI_API_KEY=''
OPENAI_API_VERSION=2024-03-01-preview
AZURE_DEPLOYMENT_NAME_GPT35="gpt-35-turbo"
AZURE_DEPLOYMENT_NAME_GPT4="gpt-4"
AZURE_EMBEDDING_TEXT_MODEL="text-embedding-ada-002"
这里各位可以依据自己的情况设定即可。
向量化+存储
上面已经说明了向量库以及embedding model的关系。我们直接使用langchain提供的工具连完成embedding和store。
#初始化embeddingmodel
fromlangchain_openaiimportAzureOpenAIEmbeddings
embeddings=AzureOpenAIEmbeddings()
fromlangchain_community.vectorstoresimportMilvus
vector=Milvus.from_documents(
documents=documents,#设置保存的文档
embedding=embeddings,#设置embeddingmodel
collection_name="book",#设置集合名称
drop_old=True,
connection_args={"host":"127.0.0.1","port":"19530"},#Milvus连接配置
)
执行完成上面的代码,我们就将pdf中文档内容保存到vector_db中。
字段vector就是保存的多维向量。
Milvus search
虽然现在我们还没有使用LLM的任何能力,但是我们已经可以使用vector的搜索功能了。
query="CodeGeeX模型API参数有那些?"
docs=vector.similarity_search(query)
print(docs)
#带score搜索
query="CodeGeeX模型API参数有那些?"
docs=vector.similarity_search_with_score(query,k=2)
print(docs)
similarity_search与similarity_search_with_score的区别就是similarity_search_with_score搜索出来会带有一个score分值的字段,某些情况下这个 score 很有用。
langchain不仅仅提供了基础的搜索能力,还有其他的搜索方法,感兴趣的可以去研究下。
RAG Chat
准备工作我们已经就绪,接下来我们使用langchain构建我们的chat。
既然是聊天也就是我们跟模型的一问一答的形式来体现。这两年LLM的出现,关于 LLM 的知识里面我们估计最熟悉就是角色设定了。
在大型语言模型(LLM)中,角色设定指的是为AI助手创建一个特定的人格或身份。这个设定包括AI助手的说话风格、知识领域、价值观、行为方式等各个方面。通过这些设定,AI助手可以扮演不同的角色,比如专业的客服、风趣幽默的聊天对象,或是特定领域的专家顾问。
角色设定可以让AI助手的回答更加符合特定的场景和用户的期望。比如一个扮演医生的AI助手,会用专业术语解释病情,给出严谨的建议;而一个扮演朋友的AI助手,会用轻松的语气聊天,给出生活化的提示。
此外,角色设定还可以帮助限定AI助手的行为边界,避免其做出不恰当或有害的回应。设定明确的角色定位,有助于AI助手更好地理解自己的身份和职责,从而提供更加合适和有帮助的回答。
总的来说,角色设定让AI助手的对话更加自然和人性化,让用户获得更好的使用体验。同时它也是引导AI助手行为、确保其安全可控的重要手段。
在 chat中我们同样也需要以及简单的prompt:
template="""Youareanassistantforquestion-answeringtasks.Usethefollowingpiecesofretrievedcontexttoanswerthequestion.Ifyoudon'tknowtheanswer,justsaythatyoudon'tknow.
Question:{question}
Context:{context}
Answer:
"""
这个prompt中很明显我们设定了两个变量question,context。
question:这个会在后面被替换为用户的输入,也就是用户的问题。
context: 这个变量我们在后面会替换为向量检索出来的内容。
请思考下:我们最后提供给LLm的内容只是用户的问题呢还是问题连带内容一起给到LLM?
chat chain
基于上面的内容我们基本的工作已经完成,下面就是我们基于langchain构建chat。
importos
fromlangchain_core.promptsimportChatPromptTemplate
prompt=ChatPromptTemplate.from_template(template)
print(prompt)
#加载chatmodel
fromlangchain_openaiimportAzureChatOpenAI
fromlangchain_core.runnablesimportRunnableParallel,RunnablePassthrough
fromlangchain_core.output_parsersimportStrOutputParser
llm=AzureChatOpenAI(
azure_deployment=os.environ.get('AZURE_DEPLOYMENT_NAME_GPT35')
)
retriever=vector.as_retriever()
chain=(
RunnableParallel({"context":retriever,"question":RunnablePassthrough()})
|prompt
|llm
|StrOutputParser()
)
对于初学者可能有个问题就是:为什么这里有个AzureChatOpenAI()的实例llm。
这是个好问题,对于初学者会被各种 LLM 搞晕??。
基于langchain的链式调用构建 chat
chain=(
RunnableParallel({"context":retriever,"question":RunnablePassthrough()})
|prompt
|llm
|StrOutputParser()
)
这里看到prompt中的两个变量context,question会被替换。
为什么我们要写变量在prompt中?
测试
示例一:
question="CodeGeeX模型API参数有那些?"
answer=chain.invoke(question)
print(answer)
输出:
CodeGeeX模型API的参数包括:
- prompt:用户输入的提示词
- max_tokens:模型输出最大tokens
- temperature:采样温度,控制输出的随机性
- top_p:另一种采样方法,模型考虑具有top_p概率质量tokens的结果
- stream:用于同步调用时,控制模型生成内容的返回方式,可以设置为false或true
示例二:
question="请给一个chat模型非流式请求示例"
answer=chain.invoke(question)
print(answer)
输出:
流式请求示例:
curl--location'http://{ip}/prod/model/api/infillingStreaming'\
--header'Content-Type:application/json'\
--data'{
"model":"codegeex",
"prompt":"packageproblem1;\nclassSolution{\npublicint\nremoveDuplicates(int[]nums){\nintcnt=1;\nfor(inti=1;\ni<nums.length;++i)\nif(nums[i]!=nums[i-1]){\n\nnums[cnt]=nums[i];\n++cnt;\n}\nreturn\ncnt;\n}\\n}",
"max_tokens":1024,
"temperature":0.2,
"top_p":0.95,
"stream":true
}'
对比pdf中的内容,很明显这个结果就是对的:
总结:
本文主要是 Milvus 向量数据实战总结。