from langchain.llms import LlamaCpp
from langchain import PromptTemplate, LLMChain
from langchain.callbacks.manager import CallbackManager
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
template = """
Context: {context}
Question: {question}
Answer:"""
context = "简单地说,肤质是皮肤的外观、触感和特性的描述。化妆品公司通常将肤质分为四大类,不过这种分类经常没用:1\.中性肤质\(皮肤没有出油或干燥的区城\)2\.油性肤质\(整个脸部的皮肤都很油,完全没有干燥的区城\)3\.干性肤质\(皮肤干燥紧绷,甚至有些脱皮,完全没有出油的区城\)4\.混合性肤质\(T字部位出油,其他部位是中性或干性肤质\)通常青春痘肤质被归类为油性或混合性皮肤,有时候也会单独被归类为一种肤质。敏感性皮肤有时也会单独被归类为一种肤质。 这四种或六种皮肤分类看起来是面面俱到了,其实肤质没有这么简单,这也是很多人搞不清自己究竟属于哪一种肤质的原因,为什么会这样呢?皮肤随时在改变,它不会永远停留在同一种肤质里面。了解自己的皮肤特性很重要,肤质绝不是化妆品公司的分。"
prompt = PromptTemplate(template=template, input_variables=["context","question"])
# Callbacks support token-wise streaming
callback_manager = CallbackManager([StreamingStdOutCallbackHandler()])
# Verbose is required to pass to the callback manager
# Make sure the model path is correct for your system!
llm = LlamaCpp(
model_path="Qwen/Qwen-7B-Chat/ggml-model-f16.gguf", callback_manager=callback_manager, verbose=True
)
llm_chain = LLMChain(prompt=prompt, llm=llm)
question = "什么是肤质?"
answer=llm_chain.run(context=context,question=question)
print(answer)
CONTEXT:简单地说,肤质是皮肤的外观、触感和特性的描述。化妆品公司通常将肤质分为四大类,不过这种分类经常没用:1\.中性肤质\(皮肤没有出油或干燥的区城\)2\.油性肤质\(整个脸部的皮肤都很油,完全没有干燥的区城\)3\.干性肤质\(皮肤干燥紧绷,甚至有些脱皮,完全没有出油的区城\)4\.混合性肤质\(T字部位出油,其他部位是中性或干性肤质\)通常青春痘肤质被归类为油性或混合性皮肤,有时候也会单独被归类为一种肤质。敏感性皮肤有时也会单独被归类为一种肤质。 这四种或六种皮肤分类看起来是面面俱到了,其实肤质没有这么简单,这也是很多人搞不清自己究竟属于哪一种肤质的原因,为什么会这样呢?皮肤随时在改变,它不会永远停留在同一种肤质里面。了解自己的皮肤特性很重要,肤质绝不是化妆品公司的分。
QUESTION:什么是肤质?
ANSWER:肤质是皮肤的外观、触感和特性的描述。简单来说,肤质是皮肤的类型。肤质通常被分为四大类:中性肤质、油性肤质、干性肤质和混合性肤质,不过这种分类并不完全准确。每个人都有不同的肤质,而且肤质会随着时间和环境的变化而改变。了解自己皮肤特性很重要,因为这可以帮助人们选择适合的护肤品。肤质并不是化妆品公司的分。
CONTEXT:#### 什么是肤质?\n\n简单地说,肤质是皮肤的外观、触感和特性的描述。\n\n化妆品公司通常将肤质分为四大类,不过这种分类经常没用:\n\n1\\.中性肤质\\(皮肤没有出油或干燥的区城\\)\n\n2\\.油性肤质\\(整个脸其他部位是中性或干性肤质\\)\n\n通常青春痘肤质被归类为油性或混合性皮肤,有时候也会单独被归类为一种肤质。敏感性皮肤有时也会单独被归类为一种肤质。 \n\n这四种或六种皮肤分类看起来是面面俱到了,其实肤质没有这么简单,这也是很多人再加上一些皮肤病,例如洒糟性皮肤炎\\(40%的白种女性有此问题\\)、湿疹、皮肤色斑、青春痘、癌前皮肤病变、黑头粉刺、阳光伤害等问题,把肤质分成四类或六类是不够的。
ANSWER:
肤质是皮肤的外观、触感和特性的描述。
肤质通常被分为四大类:
1\. 中性肤质
2\. 油性肤质
3\. 敏感性皮肤
4\. 青春痘肤质。有时还会单独被归类为一种肤质。
这四种或六种皮肤分类看起来是面面俱到了,其实肤质没有这么简单,这也是很多人再加上一些皮肤病,例如洒糟性皮肤炎、湿疹、皮肤色斑、青春痘、癌前皮肤病变、黑头粉刺、阳光伤害等问题,把肤质分成四类或六类是不够的。
这个代码是 Llama-cpp# – LangChain中文网的例子。其中的model_path文件去
在终端中输入
git clone https://www.modelscope.cn/Xorbits/Qwen-7B-Chat-GGUF.git
得到ggml-model-q4_0.gguf模型
Qwen-7B-Chat-GGUF手动下载gguf文件
结果(NO CONTEXT)
需要安装的环境:
python3.10,最高版本的gpu版本
conda install pytorch==2.1.1 torchvision==0.16.1 torchaudio==2.1.1 pytorch-cuda=12.1 -c pytorch -c nvidia
如果网络问题,就在后面加个清华源 -i https://pypi.tuna.tsinghua.edu.cn/simple ,实在不行用cpu就行了
然后
pip install langchian
pip install --no-cache-dir llama-cpp-python -i https://pypi.tuna.tsinghua.edu.cn/simple
重点:llama-cpp-python这个库windows死活安装不了,你可以了解一下怎么装,我装了两天了都不行,linux可以。
后面运行,缺什么就安装什么。能回答就说明有用。llm = LlamaCpp()函数保留下来,这个代码是来测试这个函数有没有用的。
接下来就是正式代码
import os
import torch
from langchain.chains import ConversationalRetrievalChain, RetrievalQA
from langchain.chains.question_answering import load_qa_chain
from langchain.text_splitter import MarkdownTextSplitter
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from langchain.embeddings import HuggingFaceBgeEmbeddings
from langchain.retrievers import ContextualCompressionRetriever
from langchain.retrievers.document_compressors import LLMChainExtractor
from langchain_community.llms.ollama import Ollama
from langchain_core.callbacks import CallbackManager, StreamingStdOutCallbackHandler
from langchain import PromptTemplate
from modelscope import AutoModelForCausalLM, AutoTokenizer
from langchain.memory import ConversationBufferMemory
from langchain.llms import LlamaCpp
from langchain import PromptTemplate, LLMChain
import sentence_transformers
class bd():
def __init__(self, doc_path, embedding_model_path, persist_path,llm_model_path,question):
self.doc_path = doc_path
self.embedding_model_path = embedding_model_path
self.persist_path = persist_path
self.llm_model_path = llm_model_path
self.query = question
def load_llm(self):
callback_manager=CallbackManager([StreamingStdOutCallbackHandler()])
self.llm = LlamaCpp(model_path="Qwen/Qwen-7B-Chat/ggml-model-f16.gguf", callback_manager=callback_manager, verbose=True, n_ctx=2048)
def pretty_print_docs(self):
print(f"\n{'-' * 100}\n".join([f"Document {i + 1}:\n\n" + d.page_content for i, d in enumerate(self.doc)]))
def load_data(self):
'''
加载数据
:param path: md文件路径
:return:
'''
with open(self.doc_path, 'r', encoding='utf-8') as files:
markdown_text = files.read()
markdown_splitter = MarkdownTextSplitter(chunk_size=500, chunk_overlap=50)
docs = markdown_splitter.create_documents([markdown_text]) # 分割
return docs
def embedding_data(self):
'''
embedding 数据 使用bge large zh模型,代替 openai的embeddings = OpenAIEmbeddings()
'''
self.load_data()
model_name = r"bge-large-zh"
model_kwargs = {'device': 'cpu'}
encode_kwargs = {'normalize_embeddings': True}
#self.model = sentence_transformers.SentenceTransformer(model_name)
self.model = HuggingFaceBgeEmbeddings(
model_name=model_name,
model_kwargs=model_kwargs,
encode_kwargs=encode_kwargs
)
def chroma_data(self):
'''
向量数据库,使用chroma
'''
# embedding model
self.embedding_data()
# 向量数据库保存位置
persist_directory = self.persist_path
# 检查持久化目录是否存在
if os.path.exists(persist_directory) and len(os.listdir(persist_directory)) > 0: # 检查目录是否为空
print("Chroma数据库已存在,无需重复创建.")
self.vectordb = Chroma(persist_directory=persist_directory, embedding_function=self.model)
else:
# 创建向量数据库
self.vectordb = Chroma.from_documents(
documents=self.load_data(),
embedding=self.model,
persist_directory=persist_directory
)
self.vectordb.persist() # 向量数据库的持久化
# 查看向量数据库中的文档数量
print("向量数据库中的文档数量", self.vectordb._collection.count())
def add_context_to_db(self):
'''
向原有数据库添加内容
#docsearch.add_texts(["Ankush went to Princeton"]) # 添加文本
#docsearch = Chroma.from_texts(docs, model)
'''
def retrievers(self):
'''
从向量数据库中检索与问题相关的数据方式1 mmr检索(不同的检索方式)
'''
self.load_llm()
self.chroma_data()
self.query = "什么是肤质?"
# doc = vectordb.similarity_search(query,k=3) # 寻常检索
self.doc = self.vectordb.max_marginal_relevance_search(self.query, k=3) # 使用mmr检索,可过滤相似度高的文档
# 打印文档数量
print("文档数量 ", len(self.doc))
print("第一个文档 ", self.doc[0].page_content)
'''
从向量数据库中检索与问题相关的数据方式2 上下文检索
'''
# # 上下文压缩检索
# compressor = LLMChainExtractor.from_llm(self.llm)
#
# compression_retriever = ContextualCompressionRetriever(
# base_compressor=compressor,
# base_retriever=self.vectordb.as_retriever()
# )
# question = "什么是肤质?"
# self.compressed_docs = compression_retriever.get_relevant_documents(question)
#
# print("文档数量 ", len(self.compressed_docs))
# print("第一个文档 ", self.compressed_docs[0].page_content)
def prompt_template_CRQA(self):
'''
根据检索出的结果,
构建llm-prompt提示词模板,创建新的检索方式实现对话式QA
'''
self.retrievers()
template = """
你是一个{job},我将给你一个知识文本context,以及一个与你的工作有关的问题question.
如果你在context中无法搜寻到问题的答案,即使你本身知道答案但我也请你不要回答,只需要告诉我你不知道答案就行.
知识文本为:{context},
问题为:{question}.
"""
prompt = PromptTemplate.from_template(template)
prompt.format(job="美妆达人", context=self.doc, question=self.query)
'''
对话式问答QA,基于问答QA,后面再写
'''
# memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
# qa = ConversationalRetrievalChain.from_llm(llm, vectordb.as_retriever(), memory=memory)
'''
问答QA
'''
def prompt_template_QA(self):
self.chroma_data()
self.load_llm()
query=self.query
'''
第一种代码:
'''
prompt_template = """我将给你一个知识文本context,以及一个与你的工作有关的问题question.
如果你在context中无法搜寻到问题的答案,即使你本身知道答案但我也请你不要回答,只需要告诉我你不知道答案就行.
知识文本为:{context},
问题为:{question}
"""
# PROMPT = PromptTemplate(
# template=prompt_template, input_variables=["context", "question"]
# )
# # 自定义 chain prompt
# chain_type_kwargs = {"prompt": PROMPT}
# qa = RetrievalQA.from_chain_type(llm=self.llm, chain_type="stuff", retriever=self.vectordb.as_retriever(),
# chain_type_kwargs=chain_type_kwargs)
# print(qa.run(query))
#
# '''
# 第二种代码,传上了input_documents为检索知识库出的内容
# '''
# self.retrievers()
# chain = load_qa_chain(self.llm, chain_type="stuff", prompt=PROMPT)
# answer = chain({"input_documents": self.doc, "question": query}, return_only_outputs=True)
# print(answer)
'''
第三种代码,qi he llamacpp de jicheng llm
'''
self.retrievers()
prompt = PromptTemplate(template=prompt_template, input_variables=["context","question"])
llm_chain = LLMChain(prompt=prompt, llm=self.llm)
answer=llm_chain.run(context=str(self.doc[0]),question=query)
print(answer)
if __name__ == '__main__':
doc_path = "beautiful bible.md"
embedding_model_path = r"bge-large-zh"
persist_path = 'chroma/'
llm_model_path = "ggml-model-q4_0.gguf"
question = "什么是肤质?"
bd(doc_path, embedding_model_path, persist_path,llm_model_path,question).prompt_template_QA()
只需要改md文件,随便用个简单的md文件就行了