代码是在B站上看到的 大模型RAG企业项目实战 ,先记在这里。后续还会根据自己的实际需求修改。涉及到的task主要包括 读取PDF文档、知识切片、对文本进行向量化、利用向量相似度检索出和问题最相关的k个文档,将检索到的文本注入Prompt得到最终的回答。
博客前面的 一 和 二 是对对话模型、利用Prompt实现知识注入 进行基本的讲解。第四部分是实现Langchain_RAG的基本流程。
一、环境准备
!pip install -qU \
langchain==0.0.316 \
openai==0.28.1 \
tiktoken==0.5.1 \
cohere \
chromadb==0.4.15
二、创建一个对话模型 (no RAG)
import os
from langchain.chat_models import ChatOpenAI
- 使用ChatGPT
# 调用ChatGPT
os.environ["OPENAI_API_KEY"] = "Your-API-KEY"
chat = ChatOpenAI(
openai_api_key = os.environ["OPENAI_API_KEY"],
model = 'gpt-3.5-turbo'
)
- 使用ChatGLM
国内不太方便使用ChatGPT,我们也可以用ChatOpenAI()方法调用ChatGLM
chat = ChatOpenAI(
model="glm-4",
temperature=0,
max_tokens=None,
# timeout=None,
max_retries=2,
openai_api_key="your API key", # if you prefer to pass api key in directly instaed of using env vars
openai_api_base="https://open.bigmodel.cn/api/paas/v4/",
# organization="...",
# other params...
)
需要注意的是,Langchain和ChatGPT models的输入格式不同。
ChatGPT的输入格式通常如下,具体可参看 How to format inputs to ChatGPT models:
[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Knock knock."},
{"role": "assistant", "content": "Who's there?"},
{"role": "user", "content": "Orange"},
]
Langchain的输入格式如下:
from langchain.schema import (
SystemMessage,
HumanMessage,
AIMessage
)
messages = [
SystemMessage(content="You are a helpful assistant."),
HumanMessage(content="Knock knock."),
AIMessage(content="Who's there?"),
HumanMessage(content="Orange"),
]
其中SystemMessage用于设置系统或环境的上下文,HumanMessage表示由人类发送的消息,AIMessage表示AI生成的响应。
res = chat(messages)
print(res)
模型的输出如下,为AI进一步对HumanMessage作出响应的内容。
content='Orange who?'
因为res也是AIMessage属性,所以我们可以直接进行添加,即可实现下一次的响应。
messages.append(res)
res = chat(messages)
print(res.content)
三、利用Prompt进行知识注入
有时大模型存在着 容易出现幻觉、信息滞后、专业领域深度知识匮乏 等问题,我们可以利用Prompt来进行知识注入,从而缓解该问题。
- 准备知识
baichuan2_information = [
"Baichuan 2是一个大规模多语言语言模型,它专注于训练在多种语言中表现优异的模型,包括不仅限于英文。这使得Baichuan 2在处理各种语言的任务时能够取得显著的性能提升。",
"Baichuan 2是从头开始训练的,使用了包括2.6万亿个标记的庞大训练数据集。相对于以往的模型,Baichuan 2提供了更丰富的数据资源,从而能够更好地支持多语言的开发和应用。",
"Baichuan 2不仅在通用任务上表现出色,还在特定领域(如医学和法律)的任务中展现了卓越的性能。这为特定领域的应用提供了强有力的支持。"
]
source_knowledge = "\n".join(baichuan2_information)
print(source_knowledge)
- 设计prompt_template
query = "你知道baichuan2模型吗?"
prompt_template = f"""基于以下内容回答问题:
内容:
{source_knowledge}
Query: {query}"""
- 将prompt写入messages
prompt = HumanMessage(
content = prompt_template
)
messages.append(prompt)
print(messages)
- 生成回答
res = chat(messages)
print(res)
四、创建一个RAG对话模型
这里以 baichuan2论文 为例。
- 加载数据
! pip install pypdf
from langchain.document_loaders import PyPDFLoader
loader = PyPDFLoader("https://arxiv.org/pdf/2309.10305v2.pdf")
pages = loader.load_and_split()
- 知识切片
将文档分割成均匀的块。每个块是一段原始文本。
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(
chunk_size = 500,
chunk_overlap = 50,
)
docs = text_splitter.split_documents(pages)
- 利用embedding模型对每个文本片段进行向量化,并储存到向量数据库中
(1)使用OpenAI的Embedding
from langchain.embeddings.base import Embeddings
import requests
import numpy as np
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.vectorstores import Chroma
embed_model = OpenAIEmbeddings()
vectorstore = Chroma.from_documents(documents=docs, embedding=embed_model, collection_name = "openai_embed")
(2)使用非OpenAI的Embedding
! pip install sentence-transformers
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.vectorstores import Chroma
model_name = "sentence-transformers/sentence-t5-large"
embedding = HuggingFaceEmbeddings(model_name = model_name)
vectorstore_hf = Chroma.from_documents(documents=docs, embedding=embedding, collection_name = "huggingface_embed")
- 利用向量相似度检索和问题最相关的 k 个文档
query = "How large is the baichuan2 vocabulary?"
result = vectorstore.similarity_search(query, k = 2)
# result_hf = vectorstore.similarity_search(query, k = 2)
- 原始query与检索得到的文本组合起来输入到语言模型,得到最终的回答
def augment_prompt(query: str):
# results = vectorstore.similarity_search(query, k = 3)
results = vectorstore_hf.similarity_search(query, k = 3)
source_knowledge = "\n".join([x.page_content for x in results])
augmented_prompt = f"""Using the contexts below, answer the query.
contexts:
{source_knowledge}
query: {query}"""
return augmented_prompt
print(augment_prompt(query))
prompt = HumanMessage(
content = augment_prompt(query)
)
messages.append(prompt)
res = chat(messages)
print(res.content)