logo
12

LangChain:大语言模型应用框架

文心+LangChain的应用与实现

项目结构:
安装langchain

使用1: 爬取网页并输出格式化数据

  
  
  
  
  
  
from langchain.prompts import PromptTemplate
from langchain.chains import LLMRequestsChain, LLMChain
from LLM.ChatGLM import ChatGLM
from LLM.YiYan import YiYan
# llm = ChatGLM()
llm = YiYan()
template = """在 >>> 和 <<< 之间是网页的返回的HTML内容。
网页是电影简介。
请抽取参数请求的信息。
>>> {requests_result} <<<
请使用如下的JSON格式返回数据
{{
"电影名":"a",
"导演":"b",
"主演":"c",
"上映日期":"d",
"国家/地区":"e",
"类型":"f",
"时长":"g",
"剧情简介":"h"
"豆瓣评分":"i"
}}
Extracted:"""
prompt = PromptTemplate(
input_variables=["requests_result"],
template=template
)
chain = LLMRequestsChain(llm_chain=LLMChain(llm=llm, prompt=prompt))
inputs = {
"url": "https://movie.douban.com/subject/1889243/"
}
response = chain(inputs)
print(response['output'])

使用2: 构建本地知识库问答机器人

下载模型:text2vec-base-chinese 至/shareData/目录
将知识库本地文件都放在/work/langchain/data/目录中
  
  
  
  
  
  
import os
from langchain.llms import TextGen
from langchain import PromptTemplate
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.vectorstores import Chroma
from langchain.text_splitter import CharacterTextSplitter
from langchain.document_loaders import DirectoryLoader
from langchain.chains import RetrievalQA
from LLM.ChatGLM import ChatGLM
from LLM.YiYan import YiYan
# 加载文件夹中的所有.md类型的文件
loader = DirectoryLoader('/work/langchain/data/', glob='**/*.md')
# 将数据转成 document 对象,每个文件会作为一个 document
documents = loader.load()
# 初始化加载器
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
# 切割加载的 document
split_docs = text_splitter.split_documents(documents)
# 初始化 embeddings 对象
embeddings = HuggingFaceEmbeddings(model_name='/shareData/text2vec-base-chinese')
# 将 document 计算 embedding 向量信息并临时存入 Chroma 向量数据库,用于后续匹配查询
# 持久化数据
docsearch = Chroma.from_documents(split_docs, embeddings, persist_directory="/work/langchain/Chromadb")
docsearch.persist()
# 加载数据
docsearch = Chroma(persist_directory="/work/langchain/Chromadb", embedding_function=embeddings)
# 创建问答对象
# llm = ChatGLM()
llm = YiYan()
prompt_template = """基于以下已知信息,简洁和专业的来回答用户的问题。
如果无法从中得到答案,请说 "根据已知信息无法回答该问题" 或 "没有提供足够的相关信息",不允许在答案中添加编造成分,答案请使用代码。
已知内容:
{context}
问题:
{question}"""
prompt = PromptTemplate(template=prompt_template, input_variables=["context", "question"])
chain_type_kwargs = {"prompt": prompt}
qa = RetrievalQA.from_chain_type(llm=llm, retriever=docsearch.as_retriever(), chain_type="stuff",
chain_type_kwargs=chain_type_kwargs, return_source_documents=True)
# 进行问答
query = "mongodb和redis的区别是什么"
res = qa({"query": query})
answer, docs = res['result'], res['source_documents']
print("\n\n> 问题:")
print(query)
print("\n> 回答:")
print(answer)
for document in docs:
print("\n> " + document.metadata["source"] + ":")
过程分析:1)将本地文件进行向量化存入Chromadb(常用的向量数据库有:Chroma、Pinecone、FAISS、Qdrant,参考:vector stores),2)进行问答请求,本地返回与问题相似度较高的大量文本,调用大模型进行知识抽取问答,返回结果。
其中第一步耗时较长,实际应用中可以定时任务执行知识的向量化存储,这样就不用每次问答都重新进行向量化了,节约耗时。
像这样,在不进行模型增强、模型微调的情况下,采用本地知识库向量缓存检索是一种很好的知识补充方式。

使用3: 对超长pdf文本进行总结

  
  
  
  
  
  
from langchain.document_loaders import UnstructuredFileLoader
from langchain.chains.summarize import load_summarize_chain
from langchain.text_splitter import RecursiveCharacterTextSplitter
from LLM.ChatGLM import ChatGLM
from LLM.YiYan import YiYan
# 导入文本
loader = UnstructuredFileLoader("/work/langchain/data/LLM_Survey_Chinese_V1.pdf")
# 将文本转成 Document 对象
document = loader.load()
# 初始化文本分割器
text_splitter = RecursiveCharacterTextSplitter(
chunk_size = 2000,
chunk_overlap = 0
)
# 切分文本
split_documents = text_splitter.split_documents(document)
print(f'documents:{len(split_documents)}')
# documents:100
# 加载 llm 模型
# llm = ChatGLM()
llm = YiYan()
# 创建总结链
chain = load_summarize_chain(llm, chain_type="map_reduce", verbose=True)
# 执行总结链 只取了前10段
res = chain.run(split_documents[:10])
print(res)

模型部分LLM

文心 YiYan

  
  
  
  
  
  
from typing import List, Optional
from langchain.llms.base import LLM
from langchain.llms.utils import enforce_stop_tokens
import requests
import json
WENXIN_AK = ""
WENXIN_SK = ""
def get_access_token():
"""
使用 API Key,Secret Key 获取access_token
"""
url = f"https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id={WENXIN_AK}&client_secret={WENXIN_SK}"
payload = json.dumps("")
headers = {'Content-Type': 'application/json'}
response = requests.request("POST", url, headers=headers, data=payload)
return response.json().get("access_token")
class YiYan(LLM):
temperature = 0.1 # 较高的数值会使输出更加随机,而较低的数值会使其更加集中和确定。默认0.95,范围 (0, 1.0]
top_p = 0.8 # 影响输出文本的多样性,取值越大,生成文本的多样性越强。默认0.8,取值范围 [0, 1.0]
penalty_score = 1 # 通过对已生成的token增加惩罚,减少重复生成的现象。值越大表示惩罚越大。默认1.0,取值范围:[1.0, 2.0]
def __init__(self):
super().__init__()
@property
def _llm_type(self) -> str:
return "YiYan"
def _call(self, prompt: str, stop: Optional[List[str]] = None) -> str:
url = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/eb-instant?access_token=" + get_access_token()
data = {
"messages": [{"role": "user", "content": prompt}],
"temperature": self.temperature,
"top_p": self.top_p,
"penalty_score": self.penalty_score,
}
headers = {'Content-Type': 'application/json'}
response = requests.request("POST", url, headers=headers, data=json.dumps(data))
if response.status_code == 200:
return response.json()['result']
return "查询结果错误"
if __name__ == '__main__':
url = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions?access_token=" + get_access_token()
D = {"messages": [{"role": "user", "content": "早睡早起有啥好处"}]}
data = requests.post(url, json=D, headers={"Content-Type": "application/json"})
print(data.text)

开源模型 以ChatGLM举例

其他开源模型都是类似的。
Llama2、vicuna、chatglm2、codegeex2都是支持的。
  
  
  
  
  
  
from typing import List, Optional
from langchain.llms.base import LLM
from langchain.llms.utils import enforce_stop_tokens
import requests
import json
URL = 'http://0.0.0.0:5000/api/v1/generate'
class ChatGLM(LLM):
max_new_tokens = 1000
temperature = 0.1
top_p = 1
penalty_alpha = 0
def __init__(self):
super().__init__()
@property
def _llm_type(self) -> str:
return "ChatGLM"
def _call(self, prompt: str, stop: Optional[List[str]] = None) -> str:
# headers中添加上content-type这个参数,指定为json格式
headers = {'Content-Type': 'application/json'}
data = {
'prompt': prompt,
'max_new_tokens': self.max_new_tokens,
'temperature': self.temperature,
'top_p': self.top_p,
'penalty_alpha': self.penalty_alpha,
}
# 调用api
response = requests.post(URL, headers=headers, json=data)
if response.status_code == 200:
return response.json()['results'][0]['text']
return "查询结果错误"
if __name__ == '__main__':
import requests
D = {"prompt": '累了怎么办'}
data = requests.post(URL, json=D, headers={"Content-Type": "application/json"})
print(data.text)
本文作者周洁,已获作者授权发布,如需转载请联系
评论
用户头像