基础与环境

 
https://python.langchain.com
https://python.langchain.com/v0.2/docs/introduction/
https://api.python.langchain.com/en/latest/langchain_api_reference.html

    

 
https://python.langchain.com/v0.2/docs/tutorials/

Basics
Build a Simple LLM Application with LCEL
Build a Chatbot
Build vector stores and retrievers
Build an Agent

    

 

 

    

 
现在的版本0.2相对0.1变化慢了一点,相对稳定了一点,
但也只是相对的稳定,还在不断地变化,

重点是 理解其思想,理解它的设计思想,是为了解决什么问题 

多看API , 不求甚解,不求全解,把握脉络与思想
    

常用环境

 
!pip install openai
!pip install langchain
!pip install -U langchain-community
!pip install chromadb
!pip install tiktoken
!pip install langchain_openai

.env中配置

 
# 初始化
from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv())

代码中直接引入

 
import os
os.environ["OPENAI_API_KEY"] = "sk-sb3A1ZCJXkH1kBtQ894dTwtznKQwtdfORqusPSUQ5YYA4s"
os.environ["OPENAI_BASE_URL"] = "https://api.fe8.cn/v1"

 


单纯的提问

 
from langchain_openai import OpenAI
llm = OpenAI()
llm.invoke("如何保持持续的学习")
  

 
1. 制定学习计划:制定一个详细的学习计划,包括学习的内容、时间安排、学习的目标等,以便有条理地进行学习。

2. 建立学习习惯:每天定时进行学习,养成坚持的学习习惯,可以帮助保持持续学习的动力。

3. 多渠道学习:除了传统的书籍、课堂学习外,可以利用互联网、电子书籍、视频课程等各种渠道进行学习,从不同角度获取知识。

4. 找到学习兴趣点:选择自己感兴趣的学习内容,能够激发学习的兴趣和动力。

5. 反复练习和复习:学习的效果不仅取
  

ChatOpenAI已被废弃,但也有地方依然在用

 
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model="gpt-3.5-turbo")  # 默认是gpt-3.5-turbo
response = llm.invoke("你是谁")
print(response.content)
我是一个人工智能助手,可以回答你的问题并帮助你解决问题。有什么我可以帮助你的吗?

 

  

 

  

 

  

 

  

 


模型输入

无输入,直接提问

 
from langchain_openai import OpenAI
llm = OpenAI()
llm.invoke("如何培养学习的兴趣,在学习时感受到乐趣?")
    

 
1. 找到学习的意义和价值:学习不仅仅是为了考试或者工作,它能够帮助我们提升自己的能力、增长见识、开阔思维,甚至改变命运。因此,我们应该认识到学习的意义和价值,从而激发学习的兴趣。

2. 选择感兴趣的学习内容:学习的内容应该与自己的兴趣爱好相关,这样才能更容易激发学习的兴趣。可以尝试多样的学习内容,找到自己喜欢的学科或者领域,并且不断探索和学习。

3. 制定具体的学习计划:制定学习计划可以帮助我们更有条理地学习,避免学习
    

 

    

 
from langchain_openai import OpenAI
llm = OpenAI()
    

 
from langchain.schema import (
    AIMessage,  # 等价于OpenAI接口中的assistant role
    HumanMessage,  # 等价于OpenAI接口中的user role
    SystemMessage  # 等价于OpenAI接口中的system role
)

messages = [
    SystemMessage(content="你是一个心理学家"),
    HumanMessage(content="我想学习如何与人沟通,达到心理共鸣的技巧"),
    AIMessage(content="欢迎!"),
    HumanMessage(content="你有什么建议吗?")
]

ret = llm.invoke(messages)
print(ret)
    

 
AI: 首先,沟通是双向的,要注重倾听对方的想法和感受。
其次,要保持开放的心态,尊重对方的观点,避免批评和指责。
此外,要注重非语言沟通,比如面部表情、姿势等,它们能传递更多的信息。
最后,要学会表达自己的感受和需要,让对方更容易理解你的想法。

messages本身是一个消息列表,元素是不同类型的消息

 
messages
[SystemMessage(content='你是一个心理学家'),
 HumanMessage(content='我想学习如何与人沟通,达到心理共鸣的技巧'),
 AIMessage(content='欢迎!'),
 HumanMessage(content='你有什么建议吗?')]

Document

 
from langchain.schema import Document
doc = Document(page_content="我是文档的内容",
            metadata={
            #这里可以对文档的元数据进行定义
                'my_document_id' : 11,
                'my_document_source' : "test",
                'my_document_create_time' : 1786713769,
                'my_special_info':'测试'
            })
doc
Document(metadata={
    'my_document_id': 11, 
    'my_document_source': 'test', 
    'my_document_create_time': 1786713769, 
    'my_special_info': '测试'}, 
    page_content='我是文档的内容')

 
doc = Document(page_content="人参果,中药材名。秋季采挖,晒干用。功能主治为:强心补肾,生津止渴,补脾健胃,调经活血。治神经衰弱,失眠头昏,烦躁口渴,不思饮食。.",
metadata={
    'xing' : "性温",
    'life' : "生于山坡草地"
})
doc

 
Document(metadata={
    'xing': '性温', 
    'life': '生于山坡草地'}, 
page_content='人参果,中药材名。秋季采挖,晒干用。功能主治为:强心补肾,生津止渴,补脾健胃,调经活血。治神经衰弱,失眠头昏,烦躁口渴,不思饮食。.')
    
  

 
metadata也是自定义的 键值对 ,类似于知识图谱,有了metadata,就能更好地分类
  

 

  

 
from langchain_openai import OpenAI

llm = OpenAI() 
prompt = """
我是一名40岁的男人,从事计算机行业,
我在工作的同时,想做一个副业,但这可能比较累,
是应该专注于本职工作,还是耗费时间与精力开辟一个新的赚钱的副业,

注意:
当下各行各业的就业并不好,有大量人失业,

我应该如何分配学习,工作,休息的时间,如果要选择副业,应该选择一个什么的副业?
"""
response = llm.invoke(prompt)
print(response)
  

 
作为一个40岁的男人,你已经处于事业的稳定期,应该专注于本职工作。副业可能会让你更加累,而且并不能保证稳定的收入,同时也会分散你的精力和时间。尤其是在当下就业形势不好的情况下,更需要你稳定的工作来保障自己和家人的生活。

如果你真的想要做副业,建议你选择与你本职工作相关的领域,这样可以更好地发挥你的专业知识和技能。同时,也可以利用业余时间进修相关的知识,提升自己的职业竞争力。

在分配学习、工作和休息的时间上,建议你合理安排,保证充足的休息时间,避免过度劳累。如果要选择副业

 
prompt跟“无输入”是一样的,就是一段文本,扔给LLM

后面的PromptTemplate只是在文本中添加了变量,最终给LLM的还是一个文本 

langchain以及其他对LLM的封装,都是如此,都是在设计文本以更灵活的方式迎合APP/客户,
最终给LLM还是一串字符串

 
原始的模型的输入不就是一段数据吗,从来就没有多段的,
如果有,也是合并后,一块扔给模型,
模型出的结果,也从来都是一个结果 

一个输入,模型处理,一个结果 
  

 

  

 
from langchain import PromptTemplate

template = """
你一个{role},
我想去{do},有什么建议?
"""

prompt = PromptTemplate(
    #接受用户输入
    input_variables=["role","do"],
    #定义Prompt tempalte
    template=template,
)
#这里是真正的用户输入 "北京"
final_prompt = prompt.format(role='农业科学家',do="种蔬菜水果")

print (f"组合后的用户请求: {final_prompt}")

print (f"LLM回应: {llm.invoke(final_prompt)}")

 
组合后的用户请求: 
你一个农业科学家,
我想去种蔬菜水果,有什么建议?


LLM回应: 
作为一个农业科学家,我可以给你一些建议来种植蔬菜水果:

1. 选择合适的农作物:首先,你需要根据当地的气候、土壤和市场需求来选择合适的农作物。例如,如果你所在地区气候温暖,可以种植西瓜、南瓜等热带水果,如果气候寒冷,可以选择种植胡萝卜、土豆等根茎类蔬菜。

2. 预先做好土壤准备:土壤是农作物生长的重要基础,所以你需要在种植前做好土壤准备工作。通过土壤测试,了解土壤的pH值、养分含量等情况,然后根据作物的需求施加合适的
    

 

    

 

    
模型调用

模型调用

 
模型调用就是输入一个内容给大模型,大模型处理,然后输出一个内容

用自然语言来描述就是,
问大模型一个问题,大模型给你一个答案/结果,一问一答     

 
from langchain_openai import OpenAI

llm = OpenAI() 
prompt = """
我是七三学徒,热爱新技术,对AI有浓厚的兴趣,

请问七三学徒是谁?
"""
response = llm.invoke(prompt)
print(response)
    

 
七三学徒是一个网络用戶的用户名,代表此用户是在学习中的学徒。具体身份无法确定。
    

 

    

openai

 
from openai import OpenAI

def get_completion(prompt, model="gpt-3.5-turbo-1106"):
    '''封装 openai 接口'''
    messages = [{"role": "user", "content": prompt}]
    client = OpenAI() 
    response = client.chat.completions.create(
        model=model,
        messages=messages,
        temperature=0,  # 模型输出的随机性,0 表示随机性最小
    )
    return response.choices[0].message.content
    

 
prompt = """
我是七三学徒,热爱新技术,对AI有浓厚的兴趣,

请问七三学徒是谁?
"""
get_completion(prompt)
    

 
'七三学徒是一位对新技术和人工智能有浓厚兴趣的人。可能是一个自称为七三学徒的个人或者是一个虚拟身份。'
    

封装与不封装的对比

 
langchain封装的opanai的回答,几乎没有考虑prompt中给的提示

原始openai首先考虑了prompt中给的提示,然后双加以辅助说明

 


load_qa_chain

 
from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv())
from langchain.chains.question_answering  import load_qa_chain
from langchain_openai import OpenAI
from langchain.schema import Document

 
#如果直接使用第一个doc,最后langchain会说不知道七三学徒是谁,在第二个doc中反复强调了七三学徒是谁,langchain就知道了
doc = Document(page_content="我是七三学徒,热爱新技术,对AI有浓厚的兴趣,")
doc = Document(page_content="我是七三学徒,热爱新技术,对AI有浓厚的兴趣,七三学徒就是我,我就是七三学徒")
docs=[doc]
  

 
query="请问七三学徒是谁?"
llm = OpenAI()
chain = load_qa_chain(llm=llm, chain_type="stuff")
response = chain.run(input_documents = docs, question = query)
response
  

 
' 我是七三学徒。'
  

 
doc = Document(page_content="我是七三学徒,热爱新技术,对AI有浓厚的兴趣,")
chain.run(input_documents = [doc], question = query)
  

 
' 我不知道。'
  

 
再一次证明,对于一些简单的逻辑langchain封装后,有可能处理不了

个人猜测,langchain中封装的openai版本不是最新的,所以逻辑处理能力差了一点
  

 

  

 
Tiktoken是一个Python库,由OpenAI开发,

Transformer语言模型(例如GPT-3)在训练时首先要对文本进行分词,
文本分词后的单位就是 token
- 若按单词分词,那么一个单词就是一个 token
- 若按字分词,那么一个字就是一个token 
  

 
OpenAI按token计费,Tiktoken库可以统计使用了多少token
  

 

  

 


模型输出

依赖安装

 
!pip install openai
!pip install langchain
!pip install -U langchain-community
!pip install chromadb
!pip install tiktoken
!pip install langchain_openai
    

结构体结构解析

 
结构体结构:一个key对应一个value,类似于字典,json
    

ResponseSchema定义具体的key并给出解释,StructuredOutputParser进行解析

 
from langchain.output_parsers import StructuredOutputParser, ResponseSchema
from langchain.prompts import ChatPromptTemplate, HumanMessagePromptTemplate
from langchain_openai import ChatOpenAI
from langchain import PromptTemplate

from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv())

    

  
llm = ChatOpenAI(model="gpt-3.5-turbo")  # 默认是gpt-3.5-turbo

#定义输出结构
response_schemas = [
    ResponseSchema(name="水果蔬菜", description="这里存放水果或者蔬菜类别的食物"),
    ResponseSchema(name="主食", description="这里存放主食类食物,比如馒头,大米,面条等")
]

#定义输出解析器
output_parser = StructuredOutputParser.from_response_schemas(response_schemas)

#获取输出指令
format_instructions = output_parser.get_format_instructions()
print (format_instructions)
    

 
The output should be a markdown code snippet formatted in the following schema, including the leading and trailing "```json" and "```":

```json
{
    "水果蔬菜": string  // 这里存放水果或者蔬菜类别的食物
    "主食": string  // 这里存放主食类食物,比如馒头,大米,面条等
}
```
    

 
template = """
你是一个日常生活小助手,请将下面谈话中涉及主食,水果蔬果分类,
主食一类,水果蔬菜一类

用户输入:
{user_input}

以 {format_instructions} 的格式输出
"""

prompt = PromptTemplate(
    input_variables=["user_input"],
    partial_variables={"format_instructions": format_instructions},
    template=template
)

user_input="""
我来自河南,在老家里经常吃的是面条和馒头,
但上了大学之后,食谱中增加了盖饭,
毕业后,也自己炒菜做饭了,增加了西红柿,苹果等水果蔬菜,
现在更是发现人参果这种好吃的水果
"""

promptValue = prompt.format(user_input=user_input)

print(promptValue)
    

 
你是一个日常生活小助手,请将下面谈话中涉及主食,水果蔬果分类,
主食一类,水果蔬菜一类

用户输入:

我来自河南,在老家里经常吃的是面条和馒头,
但上了大学之后,食谱中增加了盖饭,
毕业后,也自己炒菜做饭了,增加了西红柿,苹果等水果蔬菜,
现在更是发现人参果这种好吃的水果


以 The output should be a markdown code snippet formatted in the following schema, including the leading and trailing "```json" and "```":

```json
{
    "水果蔬菜": string  // 这里存放水果或者蔬菜类别的食物
    "主食": string  // 这里存放主食类食物,比如馒头,大米,面条等
}
``` 的格式输出
    

 
#大语言模型得到的结果
llm_output = llm.invoke(promptValue)

#返回给用户的结果
output_parser.parse(llm_output.content)
    

 
{'水果蔬菜': '西红柿, 苹果, 人参果', '主食': '面条, 馒头, 盖饭'}
    

 

    

 

    

 
from langchain.output_parsers import StructuredOutputParser, ResponseSchema
from langchain.prompts import ChatPromptTemplate, HumanMessagePromptTemplate
from langchain_openai import ChatOpenAI
from langchain import PromptTemplate

from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv())
    
    

 
llm = ChatOpenAI(model="gpt-3.5-turbo")  # 默认是gpt-3.5-turbo

#定义输出结构
response_schemas = [
    ResponseSchema(name="错误字符的位置", description="这里是输入错误字符在整个段落中的起始位置,一个字符为一个汉字,或者一个标点符号,第1个字符结果为1,第2个字符结果2"),
    ResponseSchema(name="错误的字符", description="这里是错误的字符"),
    ResponseSchema(name="正确的字符", description="这里是纠正以后正确的字符")
]

#定义输出解析器
output_parser = StructuredOutputParser.from_response_schemas(response_schemas)

#获取输出指令
format_instructions = output_parser.get_format_instructions()
print (format_instructions)
    

 
The output should be a markdown code snippet formatted in the following schema, including the leading and trailing "```json" and "```":

```json
{
    "错误字符的位置": string  // 这里是输入错误字符在整个段落中的起始位置,一个字符为一个汉字,或者一个标点符号,第1个字符结果为1,第2个字符结果2
    "错误的字符": string  // 这里是错误的字符
    "正确的字符": string  // 这里是纠正以后正确的字符
}
```
    

 
template = """
你是一个中文汉语的语文老师,请纠正下面下面的错别字,
特别注意代词的用法:
代词用于代替名词,以避免重复并简化表达。其中,“他”、“她”、“它”是常见的代词,分别用于指代不同的对象:
他(他):通常用于指代男性,但在某些情况下也可泛指所有的人,包括男女老幼,当性别不确定或无需明确指出性别时。
她(她):专用于指代女性。此外,在抒发感情时,人们还常将祖国、故乡、城市、学校等敬重和很有感情的事物比作“她”,以表达深厚的情感。
它(它):用于指代动物、植物、静物等没有生命的物品或抽象概念;通常不指代人物。

如果没有找到错别字,就返回None

用户输入:
{user_input}

以 {format_instructions} 的格式输出
"""

prompt = PromptTemplate(
    input_variables=["user_input"],
    partial_variables={"format_instructions": format_instructions},
    template=template
)

promptValue = prompt.format(user_input="张小雨是一名演员,作家,它小时侯学习很努力 !")

print(promptValue)
    

 
你是一个中文汉语的语文老师,请纠正下面下面的错别字,
特别注意代词的用法:
代词用于代替名词,以避免重复并简化表达。其中,“他”、“她”、“它”是常见的代词,分别用于指代不同的对象:
他(他):通常用于指代男性,但在某些情况下也可泛指所有的人,包括男女老幼,当性别不确定或无需明确指出性别时。
她(她):专用于指代女性。此外,在抒发感情时,人们还常将祖国、故乡、城市、学校等敬重和很有感情的事物比作“她”,以表达深厚的情感。
它(它):用于指代动物、植物、静物等没有生命的物品或抽象概念;通常不指代人物。

如果没有找到错别字,就返回None

用户输入:
张小雨是一名演员,作家,它小时侯学习很努力 !

以 The output should be a markdown code snippet formatted in the following schema, including the leading and trailing "```json" and "```":

```json
{
    "错误字符的位置": string  // 这里是输入错误字符在整个段落中的起始位置,一个字符为一个汉字,或者一个标点符号,第1个字符结果为1,第2个字符结果2
    "错误的字符": string  // 这里是错误的字符
    "正确的字符": string  // 这里是纠正以后正确的字符
}
``` 的格式输出
    

 
#大语言模型得到的结果
llm_output = llm.invoke(promptValue)

#返回给用户的结果
output_parser.parse(llm_output.content)

 
{'错误字符的位置': '15', '错误的字符': '它', '正确的字符': '她'}

 
错误字符的位置不准确,有一定误差,大概在这个位置附近,
但找错字还是可以的

 


 


 

  

 


文本加载切割

PyPDF2

 
from PyPDF2 import PdfReader

def extract_text_from_pdf(file_path):
    with open(file_path, 'rb') as file:
        reader = PdfReader(file)
        text = ''
        for page in reader.pages:
            text += page.extract_text()
    return text

# 使用示例
pdf_path="中医美容.pdf"
text = extract_text_from_pdf(pdf_path)
print(text)

 

    

 

    

加载文本到 langchain documents

 
from langchain_community.document_loaders import TextLoader
!echo "Text TextLoader 文本加载器">/tmp/a.txt
!echo "Text Splitters 文件分割器">>/tmp/a.txt
loader = TextLoader('/tmp/a.txt')
documents = loader.load()
documents
    

 
[Document(page_content='Text TextLoader 文本加载器\nText Splitters 文件分割器\n', metadata={'source': '/tmp/a.txt'})]

    

 

    

CharacterTextSplitter

 
# 定义一个长文本。
text = """
肺与美容的关系
肺主气主呼吸
肺主呼吸之气、一身之气。肺司呼吸的功能正常,则气道通畅,呼吸调匀,面有色泽。若病邪犯肺,影响其呼吸功能,则出现胸满咳嗽、喘促、呼吸不利、面色紫绀等症状。
肺主宣发与肃降
肺主宣发是指肺气向上升宣和向外布散的功能。
若肺气不能宣发而凝滞,清阳不升,则见胸满、鼻塞、咳喘、面色晦暗;
浊气不能肃降,也能引起呼吸短促、喘促、咳痰等症状;
肺与大肠相表里,肺失肃降,则大肠传导失常,肠道实热,表里失和,面部就易出黄褐斑或生痤疮、酒渣鼻。
肺主皮毛通调水道
肺主皮毛,是指肺脏通过它的宣发作用把水谷精微输布于皮毛,以滋养周身皮肤、毛发、肌肉,也能温分肉、充皮肤、肥腠理、司开阖,防御外邪入侵。肺气足则皮肤滋润光滑有弹性,毫毛浓密光泽等;肺气虚,不能行气与津液以温养毫毛,毫毛之营养不足,就会憔悴枯槁,皮肤干燥,毛发暗淡枯稿,面色淡白;卫外不固则易发风疹过敏等症;肺热上熏则发痤疮、酒渣鼻、皮炎等症。
肺开窍于鼻
鼻是肺呼吸的通道,所以称“鼻为肺窍”。肺与大肠相表里,肺失肃降,则大肠传导失常,粪便排出不畅。临床上,肺失清肃,则大便困难;大肠实热,又引起肺气不利而咳喘胸满;表里失和,患者面部就易出黄褐斑或生痤疮。

"""

from langchain.text_splitter import CharacterTextSplitter
text_splitter = CharacterTextSplitter(
    separator = "\n",
    chunk_size = 200,
    chunk_overlap  = 50
)

texts = text_splitter.create_documents([text])
print(texts[0].page_content)
    

 
肺与美容的关系
肺主气主呼吸
肺主呼吸之气、一身之气。肺司呼吸的功能正常,则气道通畅,呼吸调匀,面有色泽。若病邪犯肺,影响其呼吸功能,则出现胸满咳嗽、喘促、呼吸不利、面色紫绀等症状。
肺主宣发与肃降
肺主宣发是指肺气向上升宣和向外布散的功能。
若肺气不能宣发而凝滞,清阳不升,则见胸满、鼻塞、咳喘、面色晦暗;
浊气不能肃降,也能引起呼吸短促、喘促、咳痰等症状;
    

 
for text in texts:
    print(len(text.page_content))
180
83
185
106

 
要先确保以separator分割的单个文本长度不超过chunk_size
然后text_splitter才会将多个小文本段合并,合并后的文本总长也不会超过chunk_size
即text_splitter切割文本后,会保证每段文档的长度不超过chunk_size

text_splitter并不会对段落切分,
比如,你指定的separator是\n,是换行,那么就只会以换行作为切割的依据
如果PDF文档中一句话,或者一个段落很长,超出了chunk_size的大小,
此时,text_splitter以换行得到的文本必然是超出了chunk_size的大小,就会报错

因此,指定chunk_size可以根据PDF的内容,适当的设置大一些,比如1000
    
chunk_overlap  = 50
- 切割时,有可能将前后有语义关联的句子拆分到两个段落中,因此设置一定的重叠
- 如此,上下文就可以关联起来,有助于大模型的理解

text_splitter.create_documents:返回Document列表

 
texts
[Document(page_content='肺与美容的关系\n肺主气主呼吸\n肺主呼吸之气、一身之气。肺司呼吸的功能正常,则气道通畅,呼吸调匀,面有色泽。若病邪犯肺,影响其呼吸功能,则出现胸满咳嗽、喘促、呼吸不利、面色紫绀等症状。\n肺主宣发与肃降\n肺主宣发是指肺气向上升宣和向外布散的功能。\n若肺气不能宣发而凝滞,清阳不升,则见胸满、鼻塞、咳喘、面色晦暗;\n浊气不能肃降,也能引起呼吸短促、喘促、咳痰等症状;'),
 Document(page_content='浊气不能肃降,也能引起呼吸短促、喘促、咳痰等症状;\n肺与大肠相表里,肺失肃降,则大肠传导失常,肠道实热,表里失和,面部就易出黄褐斑或生痤疮、酒渣鼻。\n肺主皮毛通调水道'),
 Document(page_content='肺主皮毛通调水道\n肺主皮毛,是指肺脏通过它的宣发作用把水谷精微输布于皮毛,以滋养周身皮肤、毛发、肌肉,也能温分肉、充皮肤、肥腠理、司开阖,防御外邪入侵。肺气足则皮肤滋润光滑有弹性,毫毛浓密光泽等;肺气虚,不能行气与津液以温养毫毛,毫毛之营养不足,就会憔悴枯槁,皮肤干燥,毛发暗淡枯稿,面色淡白;卫外不固则易发风疹过敏等症;肺热上熏则发痤疮、酒渣鼻、皮炎等症。\n肺开窍于鼻'),
 Document(page_content='肺开窍于鼻\n鼻是肺呼吸的通道,所以称“鼻为肺窍”。肺与大肠相表里,肺失肃降,则大肠传导失常,粪便排出不畅。临床上,肺失清肃,则大便困难;大肠实热,又引起肺气不利而咳喘胸满;表里失和,患者面部就易出黄褐斑或生痤疮。')]
    

text_splitter.split_text

 
# 定义一个长文本。
text = """
肺与美容的关系
肺主气主呼吸
肺主呼吸之气、一身之气。肺司呼吸的功能正常,则气道通畅,呼吸调匀,面有色泽。若病邪犯肺,影响其呼吸功能,则出现胸满咳嗽、喘促、呼吸不利、面色紫绀等症状。
肺主宣发与肃降
肺主宣发是指肺气向上升宣和向外布散的功能。
若肺气不能宣发而凝滞,清阳不升,则见胸满、鼻塞、咳喘、面色晦暗;
浊气不能肃降,也能引起呼吸短促、喘促、咳痰等症状;
肺与大肠相表里,肺失肃降,则大肠传导失常,肠道实热,表里失和,面部就易出黄褐斑或生痤疮、酒渣鼻。
肺主皮毛通调水道
肺主皮毛,是指肺脏通过它的宣发作用把水谷精微输布于皮毛,以滋养周身皮肤、毛发、肌肉,也能温分肉、充皮肤、肥腠理、司开阖,防御外邪入侵。肺气足则皮肤滋润光滑有弹性,毫毛浓密光泽等;肺气虚,不能行气与津液以温养毫毛,毫毛之营养不足,就会憔悴枯槁,皮肤干燥,毛发暗淡枯稿,面色淡白;卫外不固则易发风疹过敏等症;肺热上熏则发痤疮、酒渣鼻、皮炎等症。
肺开窍于鼻
鼻是肺呼吸的通道,所以称“鼻为肺窍”。肺与大肠相表里,肺失肃降,则大肠传导失常,粪便排出不畅。临床上,肺失清肃,则大便困难;大肠实热,又引起肺气不利而咳喘胸满;表里失和,患者面部就易出黄褐斑或生痤疮。

"""

from langchain.text_splitter import CharacterTextSplitter
text_splitter = CharacterTextSplitter(
    separator = "\n",
    chunk_size = 200,
    chunk_overlap  = 50
)
    

text_splitter.split_text:返回的是文本列表

 
texts = text_splitter.split_text(text)
texts
    

 
['肺与美容的关系\n肺主气主呼吸\n肺主呼吸之气、一身之气。肺司呼吸的功能正常,则气道通畅,呼吸调匀,面有色泽。若病邪犯肺,影响其呼吸功能,则出现胸满咳嗽、喘促、呼吸不利、面色紫绀等症状。\n肺主宣发与肃降\n肺主宣发是指肺气向上升宣和向外布散的功能。\n若肺气不能宣发而凝滞,清阳不升,则见胸满、鼻塞、咳喘、面色晦暗;\n浊气不能肃降,也能引起呼吸短促、喘促、咳痰等症状;',
'浊气不能肃降,也能引起呼吸短促、喘促、咳痰等症状;\n肺与大肠相表里,肺失肃降,则大肠传导失常,肠道实热,表里失和,面部就易出黄褐斑或生痤疮、酒渣鼻。\n肺主皮毛通调水道',
'肺主皮毛通调水道\n肺主皮毛,是指肺脏通过它的宣发作用把水谷精微输布于皮毛,以滋养周身皮肤、毛发、肌肉,也能温分肉、充皮肤、肥腠理、司开阖,防御外邪入侵。肺气足则皮肤滋润光滑有弹性,毫毛浓密光泽等;肺气虚,不能行气与津液以温养毫毛,毫毛之营养不足,就会憔悴枯槁,皮肤干燥,毛发暗淡枯稿,面色淡白;卫外不固则易发风疹过敏等症;肺热上熏则发痤疮、酒渣鼻、皮炎等症。\n肺开窍于鼻',
'肺开窍于鼻\n鼻是肺呼吸的通道,所以称“鼻为肺窍”。肺与大肠相表里,肺失肃降,则大肠传导失常,粪便排出不畅。临床上,肺失清肃,则大便困难;大肠实热,又引起肺气不利而咳喘胸满;表里失和,患者面部就易出黄褐斑或生痤疮。']

文本列表转Document列表

 
from langchain.docstore.document import Document

docs = [Document(page_content=t) for t in texts[:3]]
    

 

    

RecursiveCharacterTextSplitter

 
# 定义一个长文本。
text = """
肺与美容的关系
肺主气主呼吸
肺主呼吸之气、一身之气。肺司呼吸的功能正常,则气道通畅,呼吸调匀,面有色泽。若病邪犯肺,影响其呼吸功能,则出现胸满咳嗽、喘促、呼吸不利、面色紫绀等症状。
肺主宣发与肃降
肺主宣发是指肺气向上升宣和向外布散的功能。
若肺气不能宣发而凝滞,清阳不升,则见胸满、鼻塞、咳喘、面色晦暗;
浊气不能肃降,也能引起呼吸短促、喘促、咳痰等症状;
肺与大肠相表里,肺失肃降,则大肠传导失常,肠道实热,表里失和,面部就易出黄褐斑或生痤疮、酒渣鼻。
肺主皮毛通调水道
肺主皮毛,是指肺脏通过它的宣发作用把水谷精微输布于皮毛,以滋养周身皮肤、毛发、肌肉,也能温分肉、充皮肤、肥腠理、司开阖,防御外邪入侵。肺气足则皮肤滋润光滑有弹性,毫毛浓密光泽等;肺气虚,不能行气与津液以温养毫毛,毫毛之营养不足,就会憔悴枯槁,皮肤干燥,毛发暗淡枯稿,面色淡白;卫外不固则易发风疹过敏等症;肺热上熏则发痤疮、酒渣鼻、皮炎等症。
肺开窍于鼻
鼻是肺呼吸的通道,所以称“鼻为肺窍”。肺与大肠相表里,肺失肃降,则大肠传导失常,粪便排出不畅。临床上,肺失清肃,则大便困难;大肠实热,又引起肺气不利而咳喘胸满;表里失和,患者面部就易出黄褐斑或生痤疮。

"""
    

 
from langchain_text_splitters import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(
    separators = "\n\n",
    chunk_size = 20,
    chunk_overlap  = 0
)

texts = text_splitter.create_documents([text])
print(texts[0].page_content)

 
肺与美容的关系
肺主气主呼吸

RecursiveCharacterTextSplitter功能

 
RecursiveCharacterTextSplitter是LangChain的默认文本分割器。
它采用递归的方式进行字符分割,这允许它在确保块(chunk)不过大的同时,
优先使用给定分隔符列表中的前面分隔符来分割文本。

默认情况下,它使用的分隔符列表是[“\n\n”, "\n", " ", """],这些特殊符号用于分割文本。
- 如果CharacterTextSplitter不设置拆分分隔符,那么会将整个文本作为一个chunk 
- 而RecursiveCharacterTextSplitter不设置的话,取默认值 ["\n\n", "\n", " ", """]

它考虑了分割的文本块大小(chunk_size)以及允许的前后段块重叠字符数量(chunk_overlap)。

参数:
chunk_size:分割出的块的最大长度。
- RecursiveCharacterTextSplitter拆分后,如果chunk超过指定长度,则直接舍弃
- CharacterTextSplitter也是舍弃越长的chunk,但会给一个警告性的提示

chunk_overlap:为了保持分割后语义的连贯性,设置块内前后文本的部分重叠

 
from langchain_text_splitters import CharacterTextSplitter
text_splitter = CharacterTextSplitter(
    separator = "\n",
    chunk_size = 20,
    chunk_overlap  = 0
)

texts = text_splitter.create_documents([text])
print(texts[0].page_content)
    

CharacterTextSplitter不指定separator则会为整个文本为一个chunk

 
from langchain_text_splitters import CharacterTextSplitter
text_splitter = CharacterTextSplitter(
    # separator = "\n",
    chunk_size = 20,
    chunk_overlap  = 0
)

texts = text_splitter.create_documents([text])
print(texts[0].page_content)
    

 
肺与美容的关系
肺主气主呼吸
肺主呼吸之气、一身之气。肺司呼吸的功能正常,则气道通畅,呼吸调匀,面有色泽。若病邪犯肺,影响其呼吸功能,则出现胸满咳嗽、喘促、呼吸不利、面色紫绀等症状。
肺主宣发与肃降
肺主宣发是指肺气向上升宣和向外布散的功能。
若肺气不能宣发而凝滞,清阳不升,则见胸满、鼻塞、咳喘、面色晦暗;
浊气不能肃降,也能引起呼吸短促、喘促、咳痰等症状;
肺与大肠相表里,肺失肃降,则大肠传导失常,肠道实热,表里失和,面部就易出黄褐斑或生痤疮、酒渣鼻。
肺主皮毛通调水道
肺主皮毛,是指肺脏通过它的宣发作用把水谷精微输布于皮毛,以滋养周身皮肤、毛发、肌肉,也能温分肉、充皮肤、肥腠理、司开阖,防御外邪入侵。肺气足则皮肤滋润光滑有弹性,毫毛浓密光泽等;肺气虚,不能行气与津液以温养毫毛,毫毛之营养不足,就会憔悴枯槁,皮肤干燥,毛发暗淡枯稿,面色淡白;卫外不固则易发风疹过敏等症;肺热上熏则发痤疮、酒渣鼻、皮炎等症。
肺开窍于鼻
鼻是肺呼吸的通道,所以称“鼻为肺窍”。肺与大肠相表里,肺失肃降,则大肠传导失常,粪便排出不畅。临床上,肺失清肃,则大便困难;大肠实热,又引起肺气不利而咳喘胸满;表里失和,患者面部就易出黄褐斑或生痤疮。
    

 

    

 

    

 


 

  

 


向量检索存储

嵌入数据到向量数据库

 
文本切割:
在处理文本数据时,将文本分割成更小的片段(例如单词、短语或句子)是一种常见的做法。

这是因为语言模型通常在这些更小的文本片段上进行训练,而不是在整个文档或长段落上。
这样做有几个原因:
    

 
计算效率:
处理更小的文本片段通常比处理整个文档更快,因为模型需要处理的数据量更小。

上下文理解:
在许多情况下,一个单词或短语的含义取决于其周围的上下文。
通过在更小的文本片段上进行训练,模型可以更好地理解这些上下文。

内存管理:
大型语言模型(如GPT-3或BERT)通常有一个固定的输入长度限制(例如,GPT-3的最大输入长度为2048个标记)。
将文本分割成更小的片段可以确保模型能够处理所有的输入,而不会因为输入过长而无法处理。

metadatas:
元数据是用来标识每个文本片段的来源的。
例如,"0-pl"可能表示第一个文本片段的来源,
"1-pl"表示第二个文本片段的来源,
以此类推。
    

 

    

 

    

 
!pip install openai
!pip install langchain
!pip install langchain_openai
!pip install -U langchain-community
!pip install tiktoken
!pip install chromadb
    

.env中配置

 
# 初始化
from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv())

代码中直接引入

 
import os
os.environ["OPENAI_API_KEY"] = "sk-sb3A1ZCJXkH1kBtQ894dTwtznKQwtdfORqusPSUQ5YYA4s"
os.environ["OPENAI_BASE_URL"] = "https://api.fe8.cn/v1"

 


Chroma存储示例

 
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.text_splitter import CharacterTextSplitter
from langchain.vectorstores import Chroma

from langchain_openai import OpenAI
from langchain.embeddings import OpenAIEmbeddings

from langchain.chains.qa_with_sources.retrieval import RetrievalQAWithSourcesChain

 
data="我是七三学徒,喜欢技术,对AI有浓厚的兴趣"
text_splitter = CharacterTextSplitter()
texts = text_splitter.split_text(data)
print(texts)  #['我是七三学徒,喜欢技术,对AI有浓厚的兴趣']

#选择嵌入模型
embeddings = OpenAIEmbeddings(deployment='text-embedding-ada-002')

persist_directory = 'db'
#将文本保存到Chroma 向量数据库中
docsearch = Chroma.from_texts(
    texts,
    embeddings,
    persist_directory=persist_directory,
    metadatas=[{"source":f"{i}-pl"} for i in range(len(texts))]
)

 
chain_type的值"stuff"指的是在Langchain库中使用的链的类型。

"stuff"链,也被称为StuffDocumentsChain,是一种文档链,它接收一系列文档,
将它们全部插入到一个提示中,然后将该提示传递给LLM(语言模型)。

这种链适用于文档较小且大部分调用只传入少量文档的应用。
这是一种直接的文档摘要方法。

 
llm = OpenAI()
#转换为一个检索器,进行后续的查找
retriever=docsearch.as_retriever()
chain = RetrievalQAWithSourcesChain.from_chain_type(
    llm = llm,
    #Langchain的一种文档链,接受文档
    chain_type="stuff",
    retriever=retriever,
    return_source_documents = True
)

def process_result(result):
    print(result['answer'])

question = '七三学徒是谁?'
#将字典question 作为参数传入,并获取answer作为结果
result = chain({"question":question})
process_result(result)

 
七三学徒是一个对AI有浓厚兴趣的人。

 


FAISS API

 
pip install faiss-gpu
或
pip install faiss-cpu

 
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings
from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv())

embeddings = OpenAIEmbeddings()
texts = ["FAISS is an important library", "LangChain supports FAISS"]
faiss = FAISS.from_texts(texts, embeddings)
  

embeddings.embed_documents

 
embeddings = OpenAIEmbeddings()
text_embeddings = embeddings.embed_documents(texts)
text_embedding_pairs = zip(texts, text_embeddings)
faiss = FAISS.from_embeddings(text_embedding_pairs, embeddings)
  

 
text_embeddings
[[-0.0037438378268061503,
  0.010726798344229222,
  0.0255679842524465,
  -0.021313043347900847,
  -0.009219041110042455,
  0.005944780084286135,
  -0.016802549391086254,
  8.060871200765279e-05,
  -0.03268510853906239,
  -0.01469424369478683,
  -0.011097348314241773,
  0.019511399824208027,
  0.0013168917525861008,
  ...]]

len(text_embeddings[0])
1536
  

 
def get_faiss(texts, filename):
    """根据文件名称判断是否已向量化"""
    embed_name = f"{filename}_embedding.pkl"
    embeddings = OpenAIEmbeddings()
    if os.path.exists(embed_name):
        with open(embed_name,"rb") as f:
            text_embeddings = pickle.load(f)
            # st.write("从磁盘加载向量完成")
    else:
        text_embeddings = embeddings.embed_documents(texts)
        with open(embed_name,"wb") as f:
            pickle.dump(text_embeddings,f)
        # st.write("向量化完成")
    text_embedding_pairs = zip(texts, text_embeddings)
    faiss = FAISS.from_embeddings(text_embedding_pairs, embeddings)
    return faiss
  

 
faiss = get_faiss(texts, filename="text")
faiss.similarity_search(query=query,k=1)
[Document(page_content='肺开窍于鼻\n鼻是肺呼吸的通道,所以称“鼻为肺窍”。肺与大肠相表里,肺失肃降,则大肠传导失常,粪便排出不畅。临床上,肺失清肃,则大便困难;大肠实热,又引起肺气不利而咳喘胸满;表里失和,患者面部就易出黄褐斑或生痤疮。')]

 

  

 

  

核心代码

 
query="肺与什么相表里?"
# k=1表示返回最相近的一个结果
faiss.similarity_search(query=query,k=1)

全代码

 
# 定义一个长文本。
text = """
肺与美容的关系
肺主气主呼吸
肺主呼吸之气、一身之气。肺司呼吸的功能正常,则气道通畅,呼吸调匀,面有色泽。若病邪犯肺,影响其呼吸功能,则出现胸满咳嗽、喘促、呼吸不利、面色紫绀等症状。
肺主宣发与肃降
肺主宣发是指肺气向上升宣和向外布散的功能。
若肺气不能宣发而凝滞,清阳不升,则见胸满、鼻塞、咳喘、面色晦暗;
浊气不能肃降,也能引起呼吸短促、喘促、咳痰等症状;
肺与大肠相表里,肺失肃降,则大肠传导失常,肠道实热,表里失和,面部就易出黄褐斑或生痤疮、酒渣鼻。
肺主皮毛通调水道
肺主皮毛,是指肺脏通过它的宣发作用把水谷精微输布于皮毛,以滋养周身皮肤、毛发、肌肉,也能温分肉、充皮肤、肥腠理、司开阖,防御外邪入侵。肺气足则皮肤滋润光滑有弹性,毫毛浓密光泽等;肺气虚,不能行气与津液以温养毫毛,毫毛之营养不足,就会憔悴枯槁,皮肤干燥,毛发暗淡枯稿,面色淡白;卫外不固则易发风疹过敏等症;肺热上熏则发痤疮、酒渣鼻、皮炎等症。
肺开窍于鼻
鼻是肺呼吸的通道,所以称“鼻为肺窍”。肺与大肠相表里,肺失肃降,则大肠传导失常,粪便排出不畅。临床上,肺失清肃,则大便困难;大肠实热,又引起肺气不利而咳喘胸满;表里失和,患者面部就易出黄褐斑或生痤疮。

"""

from langchain.text_splitter import CharacterTextSplitter
text_splitter = CharacterTextSplitter(
    separator = "\n",
    chunk_size = 200,
    chunk_overlap  = 50
)
texts = text_splitter.split_text(text)

 
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings
from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv())

embeddings = OpenAIEmbeddings()
faiss = FAISS.from_texts(texts, embeddings)

向量数据量返回的是当初存储的一整个chunk的数据

 
[Document(page_content='肺开窍于鼻\n鼻是肺呼吸的通道,所以称“鼻为肺窍”。肺与大肠相表里,肺失肃降,则大肠传导失常,粪便排出不畅。临床上,肺失清肃,则大便困难;大肠实热,又引起肺气不利而咳喘胸满;表里失和,患者面部就易出黄褐斑或生痤疮。')]
    

 
texts
['肺与美容的关系\n肺主气主呼吸\n肺主呼吸之气、一身之气。肺司呼吸的功能正常,则气道通畅,呼吸调匀,面有色泽。若病邪犯肺,影响其呼吸功能,则出现胸满咳嗽、喘促、呼吸不利、面色紫绀等症状。\n肺主宣发与肃降\n肺主宣发是指肺气向上升宣和向外布散的功能。\n若肺气不能宣发而凝滞,清阳不升,则见胸满、鼻塞、咳喘、面色晦暗;\n浊气不能肃降,也能引起呼吸短促、喘促、咳痰等症状;',
 '浊气不能肃降,也能引起呼吸短促、喘促、咳痰等症状;\n肺与大肠相表里,肺失肃降,则大肠传导失常,肠道实热,表里失和,面部就易出黄褐斑或生痤疮、酒渣鼻。\n肺主皮毛通调水道',
 '肺主皮毛通调水道\n肺主皮毛,是指肺脏通过它的宣发作用把水谷精微输布于皮毛,以滋养周身皮肤、毛发、肌肉,也能温分肉、充皮肤、肥腠理、司开阖,防御外邪入侵。肺气足则皮肤滋润光滑有弹性,毫毛浓密光泽等;肺气虚,不能行气与津液以温养毫毛,毫毛之营养不足,就会憔悴枯槁,皮肤干燥,毛发暗淡枯稿,面色淡白;卫外不固则易发风疹过敏等症;肺热上熏则发痤疮、酒渣鼻、皮炎等症。\n肺开窍于鼻',
 '肺开窍于鼻\n鼻是肺呼吸的通道,所以称“鼻为肺窍”。肺与大肠相表里,肺失肃降,则大肠传导失常,粪便排出不畅。临床上,肺失清肃,则大便困难;大肠实热,又引起肺气不利而咳喘胸满;表里失和,患者面部就易出黄褐斑或生痤疮。']

 

    
retriever

 
# 定义一个长文本。
text = """
肺与美容的关系
肺主气主呼吸
肺主呼吸之气、一身之气。肺司呼吸的功能正常,则气道通畅,呼吸调匀,面有色泽。若病邪犯肺,影响其呼吸功能,则出现胸满咳嗽、喘促、呼吸不利、面色紫绀等症状。
肺主宣发与肃降
肺主宣发是指肺气向上升宣和向外布散的功能。
若肺气不能宣发而凝滞,清阳不升,则见胸满、鼻塞、咳喘、面色晦暗;
浊气不能肃降,也能引起呼吸短促、喘促、咳痰等症状;
肺与大肠相表里,肺失肃降,则大肠传导失常,肠道实热,表里失和,面部就易出黄褐斑或生痤疮、酒渣鼻。
肺主皮毛通调水道
肺主皮毛,是指肺脏通过它的宣发作用把水谷精微输布于皮毛,以滋养周身皮肤、毛发、肌肉,也能温分肉、充皮肤、肥腠理、司开阖,防御外邪入侵。肺气足则皮肤滋润光滑有弹性,毫毛浓密光泽等;肺气虚,不能行气与津液以温养毫毛,毫毛之营养不足,就会憔悴枯槁,皮肤干燥,毛发暗淡枯稿,面色淡白;卫外不固则易发风疹过敏等症;肺热上熏则发痤疮、酒渣鼻、皮炎等症。
肺开窍于鼻
鼻是肺呼吸的通道,所以称“鼻为肺窍”。肺与大肠相表里,肺失肃降,则大肠传导失常,粪便排出不畅。临床上,肺失清肃,则大便困难;大肠实热,又引起肺气不利而咳喘胸满;表里失和,患者面部就易出黄褐斑或生痤疮。

"""

from langchain.text_splitter import CharacterTextSplitter
text_splitter = CharacterTextSplitter(
    separator = "\n",
    chunk_size = 200,
    chunk_overlap  = 50
)
texts = text_splitter.split_text(text)
    

 
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings
from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv())

embeddings = OpenAIEmbeddings()
faiss = FAISS.from_texts(texts, embeddings)
    

 
# 准备文件搜索器
retriever = faiss.as_retriever()

docs = retriever.invoke("鼻塞可能是什么原因?")
print("\n\n".join([x.page_content[:200] for x in docs[:3]]))
    

 
肺开窍于鼻
鼻是肺呼吸的通道,所以称“鼻为肺窍”。肺与大肠相表里,肺失肃降,则大肠传导失常,粪便排出不畅。临床上,肺失清肃,则大便困难;大肠实热,又引起肺气不利而咳喘胸满;表里失和,患者面部就易出黄褐斑或生痤疮。

浊气不能肃降,也能引起呼吸短促、喘促、咳痰等症状;
肺与大肠相表里,肺失肃降,则大肠传导失常,肠道实热,表里失和,面部就易出黄褐斑或生痤疮、酒渣鼻。
肺主皮毛通调水道

肺与美容的关系
肺主气主呼吸
肺主呼吸之气、一身之气。肺司呼吸的功能正常,则气道通畅,呼吸调匀,面有色泽。若病邪犯肺,影响其呼吸功能,则出现胸满咳嗽、喘促、呼吸不利、面色紫绀等症状。
肺主宣发与肃降
肺主宣发是指肺气向上升宣和向外布散的功能。
若肺气不能宣发而凝滞,清阳不升,则见胸满、鼻塞、咳喘、面色晦暗;
浊气不能肃降,也能引起呼吸短促、喘促、咳痰等症状;
    

 
#L2 distance in float. Lower score represents more similarity.
faiss.similarity_search_with_score("鼻塞可能是什么原因?",k=3)
    

 
[(Document(page_content='肺开窍于鼻\n鼻是肺呼吸的通道,所以称“鼻为肺窍”。肺与大肠相表里,肺失肃降,则大肠传导失常,粪便排出不畅。临床上,肺失清肃,则大便困难;大肠实热,又引起肺气不利而咳喘胸满;表里失和,患者面部就易出黄褐斑或生痤疮。'),
0.2922338),
(Document(page_content='浊气不能肃降,也能引起呼吸短促、喘促、咳痰等症状;\n肺与大肠相表里,肺失肃降,则大肠传导失常,肠道实热,表里失和,面部就易出黄褐斑或生痤疮、酒渣鼻。\n肺主皮毛通调水道'),
0.32967678),
(Document(page_content='肺与美容的关系\n肺主气主呼吸\n肺主呼吸之气、一身之气。肺司呼吸的功能正常,则气道通畅,呼吸调匀,面有色泽。若病邪犯肺,影响其呼吸功能,则出现胸满咳嗽、喘促、呼吸不利、面色紫绀等症状。\n肺主宣发与肃降\n肺主宣发是指肺气向上升宣和向外布散的功能。\n若肺气不能宣发而凝滞,清阳不升,则见胸满、鼻塞、咳喘、面色晦暗;\n浊气不能肃降,也能引起呼吸短促、喘促、咳痰等症状;'),
0.34343675)]
    

 
faiss.similarity_search_with_relevance_scores("鼻塞可能是什么原因?")
    

 
[(Document(page_content='肺开窍于鼻\n鼻是肺呼吸的通道,所以称“鼻为肺窍”。肺与大肠相表里,肺失肃降,则大肠传导失常,粪便排出不畅。临床上,肺失清肃,则大便困难;大肠实热,又引起肺气不利而咳喘胸满;表里失和,患者面部就易出黄褐斑或生痤疮。'),
0.7933595019148172),
(Document(page_content='浊气不能肃降,也能引起呼吸短促、喘促、咳痰等症状;\n肺与大肠相表里,肺失肃降,则大肠传导失常,肠道实热,表里失和,面部就易出黄褐斑或生痤疮、酒渣鼻。\n肺主皮毛通调水道'),
0.7668833152956073),
(Document(page_content='肺与美容的关系\n肺主气主呼吸\n肺主呼吸之气、一身之气。肺司呼吸的功能正常,则气道通畅,呼吸调匀,面有色泽。若病邪犯肺,影响其呼吸功能,则出现胸满咳嗽、喘促、呼吸不利、面色紫绀等症状。\n肺主宣发与肃降\n肺主宣发是指肺气向上升宣和向外布散的功能。\n若肺气不能宣发而凝滞,清阳不升,则见胸满、鼻塞、咳喘、面色晦暗;\n浊气不能肃降,也能引起呼吸短促、喘促、咳痰等症状;'),
0.7571535467294733),
(Document(page_content='肺主皮毛通调水道\n肺主皮毛,是指肺脏通过它的宣发作用把水谷精微输布于皮毛,以滋养周身皮肤、毛发、肌肉,也能温分肉、充皮肤、肥腠理、司开阖,防御外邪入侵。肺气足则皮肤滋润光滑有弹性,毫毛浓密光泽等;肺气虚,不能行气与津液以温养毫毛,毫毛之营养不足,就会憔悴枯槁,皮肤干燥,毛发暗淡枯稿,面色淡白;卫外不固则易发风疹过敏等症;肺热上熏则发痤疮、酒渣鼻、皮炎等症。\n肺开窍于鼻'),
0.7258311679545109)]
    

 

    

 
# 定义一个长文本。
text = """
肺与美容的关系
肺主气主呼吸
肺主呼吸之气、一身之气。肺司呼吸的功能正常,则气道通畅,呼吸调匀,面有色泽。若病邪犯肺,影响其呼吸功能,则出现胸满咳嗽、喘促、呼吸不利、面色紫绀等症状。
肺主宣发与肃降
肺主宣发是指肺气向上升宣和向外布散的功能。
若肺气不能宣发而凝滞,清阳不升,则见胸满、鼻塞、咳喘、面色晦暗;
浊气不能肃降,也能引起呼吸短促、喘促、咳痰等症状;
肺与大肠相表里,肺失肃降,则大肠传导失常,肠道实热,表里失和,面部就易出黄褐斑或生痤疮、酒渣鼻。
肺主皮毛通调水道
肺主皮毛,是指肺脏通过它的宣发作用把水谷精微输布于皮毛,以滋养周身皮肤、毛发、肌肉,也能温分肉、充皮肤、肥腠理、司开阖,防御外邪入侵。肺气足则皮肤滋润光滑有弹性,毫毛浓密光泽等;肺气虚,不能行气与津液以温养毫毛,毫毛之营养不足,就会憔悴枯槁,皮肤干燥,毛发暗淡枯稿,面色淡白;卫外不固则易发风疹过敏等症;肺热上熏则发痤疮、酒渣鼻、皮炎等症。
肺开窍于鼻
鼻是肺呼吸的通道,所以称“鼻为肺窍”。肺与大肠相表里,肺失肃降,则大肠传导失常,粪便排出不畅。临床上,肺失清肃,则大便困难;大肠实热,又引起肺气不利而咳喘胸满;表里失和,患者面部就易出黄褐斑或生痤疮。

"""
    

 
鼻塞可能是什么原因?

其实是问的下面这句话 
若肺气不能宣发而凝滞,清阳不升,则见胸满、鼻塞、咳喘、面色晦暗;

这属于语义的理解

 
但向量数据库,或者说 按相关性分析,L2距离计算出来的结果看,
期望的答案没有排进前二名,排到了第3位 
所以,稍微严格的场景下,应该将搜索前三的结果 送给LLM 

由LLM进行语义理解 

 


 


 

  

 


摘要

 
from langchain_openai import OpenAI
from langchain_openai import OpenAIEmbeddings
from langchain import PromptTemplate
from langchain.chains.question_answering  import load_qa_chain
from langchain.chains.summarize import load_summarize_chain
# 初始化
from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv())
    

 
# 定义一个长文本。
text = """
肺与美容的关系
肺主气主呼吸
肺主呼吸之气、一身之气。肺司呼吸的功能正常,则气道通畅,呼吸调匀,面有色泽。若病邪犯肺,影响其呼吸功能,则出现胸满咳嗽、喘促、呼吸不利、面色紫绀等症状。
肺主宣发与肃降
肺主宣发是指肺气向上升宣和向外布散的功能。
若肺气不能宣发而凝滞,清阳不升,则见胸满、鼻塞、咳喘、面色晦暗;
浊气不能肃降,也能引起呼吸短促、喘促、咳痰等症状;
肺与大肠相表里,肺失肃降,则大肠传导失常,肠道实热,表里失和,面部就易出黄褐斑或生痤疮、酒渣鼻。
肺主皮毛通调水道
肺主皮毛,是指肺脏通过它的宣发作用把水谷精微输布于皮毛,以滋养周身皮肤、毛发、肌肉,也能温分肉、充皮肤、肥腠理、司开阖,防御外邪入侵。肺气足则皮肤滋润光滑有弹性,毫毛浓密光泽等;肺气虚,不能行气与津液以温养毫毛,毫毛之营养不足,就会憔悴枯槁,皮肤干燥,毛发暗淡枯稿,面色淡白;卫外不固则易发风疹过敏等症;肺热上熏则发痤疮、酒渣鼻、皮炎等症。
肺开窍于鼻
鼻是肺呼吸的通道,所以称“鼻为肺窍”。肺与大肠相表里,肺失肃降,则大肠传导失常,粪便排出不畅。临床上,肺失清肃,则大便困难;大肠实热,又引起肺气不利而咳喘胸满;表里失和,患者面部就易出黄褐斑或生痤疮。

"""

from langchain.text_splitter import CharacterTextSplitter
text_splitter = CharacterTextSplitter(
    separator = "\n",
    chunk_size = 200,
    chunk_overlap  = 50
)

docs = text_splitter.create_documents([text])
    

 
prompt_template = """根据下面的内容生成摘要:

{text}

摘要内容以中文显示,并且不超过三句话:"""
PROMPT = PromptTemplate(template=prompt_template, input_variables=["text"])
PROMPT
#PromptTemplate(input_variables=['text'], template='根据下面的内容生成摘要:\n\n{text}\n\n摘要内容以中文显示,并且不超过三句话:')

 
llm = OpenAI()
chain = load_summarize_chain(llm, chain_type="stuff", prompt=PROMPT)
    

 
chain.run(docs)
'\n\n肺主气主呼吸,若功能受影响则会出现呼吸困难、胸满咳嗽等症状。肺主宣发与肃降,若失调则易导致肤质问题如黄褐斑、毛发枯槁等。肺开窍于鼻,失调则会影响大肠功能,出现大便不畅、咳喘等症状。'

load_summarize_chain官方示例

 
https://python.langchain.com/v0.2/docs/integrations/callbacks/infino/
Example 2: Summarize a piece of text using ChatOpenAI
    

 
# Set your key here.
# os.environ["OPENAI_API_KEY"] = "YOUR_API_KEY"

from langchain.chains.summarize import load_summarize_chain
from langchain_community.document_loaders import WebBaseLoader
from langchain_openai import ChatOpenAI

# Create callback handler. This logs latency, errors, token usage, prompts, as well as prompt responses to Infino.
handler = InfinoCallbackHandler(
    model_id="test_chatopenai", model_version="0.1", verbose=False
)

urls = [
    "https://lilianweng.github.io/posts/2023-06-23-agent/",
    "https://medium.com/lyft-engineering/lyftlearn-ml-model-training-infrastructure-built-on-kubernetes-aef8218842bb",
    "https://blog.langchain.dev/week-of-10-2-langchain-release-notes/",
]

for url in urls:
    loader = WebBaseLoader(url)
    docs = loader.load()

    llm = ChatOpenAI(temperature=0, model_name="gpt-3.5-turbo-16k", callbacks=[handler])
    chain = load_summarize_chain(llm, chain_type="stuff", verbose=False)

    chain.run(docs)
    

 

    

 

    

 


 

  

 


参考
     Huggingface 镜像站