AI大模型学习(四): LangChain(三)
Langchain构建代理
语言模型本身无法执行动作,他们只能输出文本,代理是使用大型语言模型(LLM)作为推理引擎来确定要执行的操作以及这些操作的输入应该是什么,然后这些操作的结果可以反馈到代理中,代理将决定是否需要更多的操作,或者是否可以结束
例如:我们想要查询现在北京的天气,这个天气结果因为是事实变化的,大语言模型他的训练资料是之前的没办法获取现在的天气情况,需要去调用代理去获取结果
安装包
pip install langgraph
使用大模型直接查询天气
from langchain_core.messages import HumanMessage
from langchain_openai import ChatOpenAI
import oskey = ''
os.environ["OPENAI_API_KEY"] = key
model = ChatOpenAI(model='gpt-4')result = model.invoke([HumanMessage(content='上海今天天气怎么样?')
])
print(result.content)
# 对不起,作为一个AI,我无法提供实时信息,包括天气信息。你可以通过搜索或者使用天气应用来获得这些信息
我们可以看到LLM他是没办法获取到实时的天气情况,这个时候就需要代理
使用tavily配合大模型
配置TAVILY_API_KEY
官网链接:Tavily AI
简单使用tavily
from langchain_openai import ChatOpenAI
from langchain_community.tools.tavily_search import TavilySearchResults
import oskey = ''
os.environ["OPENAI_API_KEY"] = key
os.environ["TAVILY_API_KEY"] = ""
model = ChatOpenAI(model='gpt-4')# Langchain内置了一个工具,可以轻松地使用Taviky搜索引擎作为工具
search = TavilySearchResults(max_results=2) # max_results只返回两个结果
print(search.invoke('上海今天天气怎么样?'))
"""
[{'url': 'https://tianqi.moji.com/today/china/shanghai/shanghai', 'content': '首页 天气 下载 资讯 关于墨迹 天气 中国 上海市, 上海市, 中国 热门时景 更多 附近地区 更多 附近景点 更多 1 晴 晴 2°日出 06:41 晴 -2°日落 17:35 晴 02/07 * 周六 晴 晴 02/08 * 周日 晴 晴 02/09 * 周一 多云 阴 02/10 * 周二 阴 小雨 02/11 阴 02/12 * 周四 阴 阴 02/13 * 周五 小雨 小雨 02/14 * 周六 小雨 多云 02/15 * 周日 晴 多云 02/16 * 周一 阴 阴 02/17 * 周二 阴 多云 02/18 * 周三 晴 阴 02/19 晴 02/20 * 周五 晴 阴 02/21 阴 02/22 较适宜 狗狗 不适宜 猫咪 不适宜 运动 较适宜 广场舞 较适宜 钓鱼 不适宜 啤酒 较适宜 夜生活 不宜 放风筝 较适宜 旅游 不宜 晨练 较适宜 洗车 较适宜 逛街 pm2.5 pm2.5省份列表 pm2.5城市列表'}, {'url': 'https://weather.cma.cn/web/weather/58367.html', 'content': '主站首页 领导主站 部门概况 新闻资讯 信息公开 服务办事 天气预报 首页 天气实况 气象公报 气象预警 城市预报 天气资讯 气象专题 气象科普 首页 国内 上海 徐家汇 国内 上海 徐家汇 更新 7天天气预报(2025/02/08 08:00发布) 星期六 无持续风向 微风 2℃ -2℃ 无持续风向 微风 星期日 无持续风向 微风 4℃ 0℃ 无持续风向 微风 星期一 多云 无持续风向 微风 9℃ 4℃ 无持续风向 微风 星期二 无持续风向 微风 12℃ 7℃ 小雨 无持续风向 微风 星期三 小雨 东北风 3~4级 10℃ 4℃ 北风 3~4级 星期四 无持续风向 微风 10℃ 2℃ 无持续风向 微风 星期五 小雨 无持续风向 微风 8℃ 4℃ 小雨 东风 3~4级 时间 11:00 14:00 17:00 20:00 23:00 02:00 05:00 08:00 天气 气温 0.7℃ 2℃ 1.4℃ -0.2℃ -1.1℃ -1.8℃ -1.9℃ -1.1℃ 降水 无降水 无降水 无降水 无降水 无降水 无降水 无降水 无降水 风速 3.2m/s 3.3m/s 2.7m/s 2.6m/s 3.1m/s 3.3m/s 3m/s 3.2m/s 南方地区有较大范围雨雪天气 琼州海峡等海域有大雾 中东部地区有较大范围雨雪过程 琼州海峡等海域有大雾 中东部地区有较大范围雨雪过程'}]
"""
上面的返回结果是查询了两个一个是从url:'https://tianqi.moji.com/today/china/shanghai/shanghai'获取,另一个是'https://weather.cma.cn/web/weather/58367.html' 这是因为我们最大获取的是2个
from langchain_core.messages import HumanMessage
from langchain_openai import ChatOpenAI
from langchain_community.tools.tavily_search import TavilySearchResults
import osfrom langgraph.prebuilt import chat_agent_executorkey = ''
os.environ["OPENAI_API_KEY"] = key
os.environ["TAVILY_API_KEY"] = ""
model = ChatOpenAI(model='gpt-4')# Langchain内置了一个工具,可以轻松地使用Taviky搜索引擎作为工具
search = TavilySearchResults(max_results=2) # max_results只返回两个结果# 让模型绑定工具
model_and_tool = model.bind_tools([search])
response = model_and_tool.invoke([HumanMessage(content="上海今天天气怎么样?")
])
print(f'model_result:{response.content}')
# 这个为空,证明LLM本身并没有回答答案,所以调用了工具
print(f'model_result:{response.tool_calls}')
# 这个是一个搜索的指令,要代理去调用工具
# model_result:[{'name': 'tavily_search_results_json', 'args': {'query': '上海今天天气'}, 'id': 'call_S4CKoL0UHaMBtHEa5COUgvhc', 'type': 'tool_call'}]
AI+代理
from langchain_core.messages import HumanMessage
from langchain_openai import ChatOpenAI
from langchain_community.tools.tavily_search import TavilySearchResults
import osfrom langgraph.prebuilt import chat_agent_executorkey = ''
os.environ["OPENAI_API_KEY"] = key
os.environ["TAVILY_API_KEY"] = "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"
model = ChatOpenAI(model='gpt-4')# Langchain内置了一个工具,可以轻松地使用Taviky搜索引擎作为工具
search = TavilySearchResults(max_results=1) # max_results只返回两个结果# 让模型绑定工具
tool = [search]# 创建代理
agent_executor = chat_agent_executor.create_tool_calling_executor(model, tool)# 这里有个坑必须是messages,写message会报错的
response = agent_executor.invoke({'messages': [HumanMessage(content="上海今天天气怎么样?")]}
)
# print(response['messages'])
# 返回是一个特殊的格式
# [HumanMessage(content='上海今天天气怎么样?', additional_kwargs={}, response_metadata={}, id='9670a4fb-06b4-42a1-bf46-a9455cdd72ef'),
# AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_MPM8ATtgU1R3d9X9mF9IZxZ1', 'function': {'arguments': '{\n "query": "上海今天天气"\n}', 'name': 'tavily_search_results_json'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 26, 'prompt_tokens': 93, 'total_tokens': 119, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4-0613', 'system_fingerprint': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-c6635a96-a3f4-46e8-8edd-36183d7da62e-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': '上海今天天气'}, 'id': 'call_MPM8ATtgU1R3d9X9mF9IZxZ1', 'type': 'tool_call'}], usage_metadata={'input_tokens': 93, 'output_tokens': 26, 'total_tokens': 119, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}}),
# ToolMessage(content='[{"url": "https://tianqi.moji.com/today/china/shanghai/shanghai", "content": "首页 天气 下载 资讯 关于墨迹 天气 中国 上海市, 上海市, 中国 热门时景 更多 附近地区 更多 附近景点 更多 1 晴 晴 2°日出 06:41 晴 -2°日落 17:35 晴 02/07 * 周六 晴 晴 02/08 * 周日 晴 晴 02/09 * 周一 多云 阴 02/10 * 周二 阴 小雨 02/11 阴 02/12 * 周四 阴 阴 02/13 * 周五 小雨 小雨 02/14 * 周六 小雨 多云 02/15 * 周日 晴 多云 02/16 * 周一 阴 阴 02/17 * 周二 阴 多云 02/18 * 周三 晴 阴 02/19 晴 02/20 * 周五 晴 阴 02/21 阴 02/22 较适宜 狗狗 不适宜 猫咪 不适宜 运动 较适宜 广场舞 较适宜 钓鱼 不适宜 啤酒 较适宜 夜生活 不宜 放风筝 较适宜 旅游 不宜 晨练 较适宜 洗车 较适宜 逛街 pm2.5 pm2.5省份列表 pm2.5城市列表"}, {"url": "https://weather.cma.cn/web/weather/58367.html", "content": "主站首页 领导主站 部门概况 新闻资讯 信息公开 服务办事 天气预报 首页 天气实况 气象公报 气象预警 城市预报 天气资讯 气象专题 气象科普 首页 国内 上海 徐家汇 国内 上海 徐家汇 更新 7天天气预报(2025/02/08 08:00发布) 星期六 无持续风向 微风 2℃ -2℃ 无持续风向 微风 星期日 无持续风向 微风 4℃ 0℃ 无持续风向 微风 星期一 多云 无持续风向 微风 9℃ 4℃ 无持续风向 微风 星期二 无持续风向 微风 12℃ 7℃ 小雨 无持续风向 微风 星期三 小雨 东北风 3~4级 10℃ 4℃ 北风 3~4级 星期四 无持续风向 微风 10℃ 2℃ 无持续风向 微风 星期五 小雨 无持续风向 微风 8℃ 4℃ 小雨 东风 3~4级 时间 11:00 14:00 17:00 20:00 23:00 02:00 05:00 08:00 天气 气温 0.7℃ 2℃ 1.4℃ -0.2℃ -1.1℃ -1.8℃ -1.9℃ -1.1℃ 降水 无降水 无降水 无降水 无降水 无降水 无降水 无降水 无降水 风速 3.2m/s 3.3m/s 2.7m/s 2.6m/s 3.1m/s 3.3m/s 3m/s 3.2m/s 南方地区有较大范围雨雪天气 琼州海峡等海域有大雾 中东部地区有较大范围雨雪过程 琼州海峡等海域有大雾 中东部地区有较大范围雨雪过程"}]', name='tavily_search_results_json', id='99e42bba-8415-468a-8565-3414548235af', tool_call_id='call_MPM8ATtgU1R3d9X9mF9IZxZ1', artifact={'query': '上海今天天气', 'follow_up_questions': None, 'answer': None, 'images': [], 'results': [{'url': 'https://tianqi.moji.com/today/china/shanghai/shanghai', 'title': '今天上海市天气_今日天气预报- 墨迹天气', 'content': '首页 天气 下载 资讯 关于墨迹 天气 中国 上海市, 上海市, 中国 热门时景 更多 附近地区 更多 附近景点 更多 1 晴 晴 2°日出 06:41 晴 -2°日落 17:35 晴 02/07 * 周六 晴 晴 02/08 * 周日 晴 晴 02/09 * 周一 多云 阴 02/10 * 周二 阴 小雨 02/11 阴 02/12 * 周四 阴 阴 02/13 * 周五 小雨 小雨 02/14 * 周六 小雨 多云 02/15 * 周日 晴 多云 02/16 * 周一 阴 阴 02/17 * 周二 阴 多云 02/18 * 周三 晴 阴 02/19 晴 02/20 * 周五 晴 阴 02/21 阴 02/22 较适宜 狗狗 不适宜 猫咪 不适宜 运动 较适宜 广场舞 较适宜 钓鱼 不适宜 啤酒 较适宜 夜生活 不宜 放风筝 较适宜 旅游 不宜 晨练 较适宜 洗车 较适宜 逛街 pm2.5 pm2.5省份列表 pm2.5城市列表', 'score': 0.8315952, 'raw_content': None}, {'url': 'https://weather.cma.cn/web/weather/58367.html', 'title': '中国气象局-天气预报-城市预报- 上海', 'content': '主站首页 领导主站 部门概况 新闻资讯 信息公开 服务办事 天气预报 首页 天气实况 气象公报 气象预警 城市预报 天气资讯 气象专题 气象科普 首页 国内 上海 徐家汇 国内 上海 徐家汇 更新 7天天气预报(2025/02/08 08:00发布) 星期六 无持续风向 微风 2℃ -2℃ 无持续风向 微风 星期日 无持续风向 微风 4℃ 0℃ 无持续风向 微风 星期一 多云 无持续风向 微风 9℃ 4℃ 无持续风向 微风 星期二 无持续风向 微风 12℃ 7℃ 小雨 无持续风向 微风 星期三 小雨 东北风 3~4级 10℃ 4℃ 北风 3~4级 星期四 无持续风向 微风 10℃ 2℃ 无持续风向 微风 星期五 小雨 无持续风向 微风 8℃ 4℃ 小雨 东风 3~4级 时间 11:00 14:00 17:00 20:00 23:00 02:00 05:00 08:00 天气 气温 0.7℃ 2℃ 1.4℃ -0.2℃ -1.1℃ -1.8℃ -1.9℃ -1.1℃ 降水 无降水 无降水 无降水 无降水 无降水 无降水 无降水 无降水 风速 3.2m/s 3.3m/s 2.7m/s 2.6m/s 3.1m/s 3.3m/s 3m/s 3.2m/s 南方地区有较大范围雨雪天气 琼州海峡等海域有大雾 中东部地区有较大范围雨雪过程 琼州海峡等海域有大雾 中东部地区有较大范围雨雪过程', 'score': 0.7539928, 'raw_content': None}], 'response_time': 1.09}), AIMessage(content='根据搜索结果,上海的天气状况如下:今天是晴天,温度介于-2℃~2℃之间。下个星期的天气预报,周一多云,周二至周五有小雨。同时,近期空气质量良好,适宜出行。[天气信息来源](https://tianqi.moji.com/today/china/shanghai/shanghai)', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 116, 'prompt_tokens': 1358, 'total_tokens': 1474, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4-0613', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-16c1ee88-b95b-4030-9a76-45d22dcc8a48-0', usage_metadata={'input_tokens': 1358, 'output_tokens': 116, 'total_tokens': 1474, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})]
"""
HumanMessage:用户输入
AIMessage:大模型返回的消息
ToolMessage:Agent返回的消息
"""# 我们就可以这样去判断,如果有Ai返回则用Ai没有则用工具
def get_message(result):if result[1].content:return result[1].contentreturn result[2].contentprint(get_message(response['messages']))
"""
[{"url": "https://weather.cma.cn/web/weather/58367.html", "content": "主站首页 领导主站 部门概况 新闻资讯 信息公开 服务办事 天气预报 首页 天气实况 气象公报 气象预警 城市预报 天气资讯 气象专题 气象科普 首页 国内 上海 徐家汇 国内 上海 徐家汇 更新 7天天气预报(2025/02/08 08:00发布) 星期六 无持续风向 微风 2℃ -2℃ 无持续风向 微风 星期日 无持续风向 微风 4℃ 0℃ 无持续风向 微风 星期一 多云 无持续风向 微风 9℃ 4℃ 无持续风向 微风 星期二 无持续风向 微风 12℃ 7℃ 小雨 无持续风向 微风 星期三 小雨 东北风 3~4级 10℃ 4℃ 北风 3~4级 星期四 无持续风向 微风 10℃ 2℃ 无持续风向 微风 星期五 小雨 无持续风向 微风 8℃ 4℃ 小雨 东风 3~4级 时间 11:00 14:00 17:00 20:00 23:00 02:00 05:00 08:00 天气 气温 0.7℃ 2℃ 1.4℃ -0.2℃ -1.1℃ -1.8℃ -1.9℃ -1.1℃ 降水 无降水 无降水 无降水 无降水 无降水 无降水 无降水 无降水 风速 3.2m/s 3.3m/s 2.7m/s 2.6m/s 3.1m/s 3.3m/s 3m/s 3.2m/s 南方地区有较大范围雨雪天气 琼州海峡等海域有大雾 中东部地区有较大范围雨雪过程 琼州海峡等海域有大雾 中东部地区有较大范围雨雪过程"}]
"""
Langchain构建RAG的对话应用
案例:复杂的问答(Q&A)聊天机器人,应用程序可以回答有关特定源信息的问题,使用一种称为检索增强生成(RAG)的技术
RAG是一种增强LLM知识的方法,它通过引入额外的数据来实现
安装包
pip install langgraph
实现思路:
1.加载:首先我们需要加载数据,这是通过DocumentLoaders完成的
2.分割:Text splitters 将大型文档分割成更小的快,这对于索引数据和将其传递给模型很有用,因为大数据块更难搜索,并且不适合模型有限上下文窗口
3.存储:我们需要一个地方来存储和索引我们的分割,以便以后可以搜索,这通常使用VectorStore和Embeddings模型完成
4.检索:给定用户输入,使用检索器从存储中检索相关分割
5.生成:ChatModel/LLM使用包括问题和检索到的数据的提示生成答案
简单不包含历史记录的实现
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain.chains.retrieval import create_retrieval_chain
from langchain_chroma import Chroma
from langchain_community.document_loaders import WebBaseLoader
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter
import os
import bs4key = ''
os.environ["OPENAI_API_KEY"] = key
model = ChatOpenAI(model='gpt-4')# 1.加载数据:一篇博客内容数据
# web_paths 爬取内容的url地址,可以一次性写多个
loader = WebBaseLoader(web_paths=['http://lilianweng.github.io//posts/2023-06-23-agent/'],bs_kwargs=dict(parse_only=bs4.SoupStrainer(class_=('post-header', 'post-title', 'post-content')) # class_这个是html页面的类选择器)
)
desc = loader.load() # 将博客内容解析出来
# 2.大文本切割
splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=20)# 切割documents对象,切文本用split_text,传入字符串
res = splitter.split_documents(desc)# 3.存储
vectorstore = Chroma.from_documents(documents=res, embedding=OpenAIEmbeddings())# 4.检索器
retriever = vectorstore.as_retriever()# 5.整合# 6.创建一个问题的模版system_prompt = """
You are an assistant for question-answering tasks.Use the following pieces of
retrieved context to answer the question.If you don't know how to answer say that you don't know
Use the sentences maximum and keep the answer concise.\n{context}
"""prompt = ChatPromptTemplate.from_messages([('system', system_prompt),# MessagesPlaceholder("chat_history"), # 提问的历史记录('human', '{input}')
])# 7.得到chain
# 提问的chain
chain_one = create_stuff_documents_chain(model, prompt)
# 检索器+问答
chain_two = create_retrieval_chain(retriever, chain_one)response = chain_two.invoke({'input': 'What is Task Decomposition'})
# print(response)
"""
{'input': 'What is Task Decomposition',
'context': [Document(id='c85ca1e7-7370-41dd-bab1-53bfe4cc7d42', metadata={'source': 'http://lilianweng.github.io//posts/2023-06-23-agent/'}, page_content='Fig. 1. Overview of a LLM-powered autonomous agent system.\nComponent One: Planning#\nA complicated task usually involves many steps. An agent needs to know what they are and plan ahead.\nTask Decomposition#\nChain of thought (CoT; Wei et al. 2022) has become a standard prompting technique for enhancing model performance on complex tasks. The model is instructed to “think step by step” to utilize more test-time computation to decompose hard tasks into smaller and simpler steps. CoT transforms big tasks into multiple manageable tasks and shed lights into an interpretation of the model’s thinking process.'), Document(id='7d97c299-2160-45da-8936-9466bb055e10', metadata={'source': 'http://lilianweng.github.io//posts/2023-06-23-agent/'}, page_content='Tree of Thoughts (Yao et al. 2023) extends CoT by exploring multiple reasoning possibilities at each step. It first decomposes the problem into multiple thought steps and generates multiple thoughts per step, creating a tree structure. The search process can be BFS (breadth-first search) or DFS (depth-first search) with each state evaluated by a classifier (via a prompt) or majority vote.\nTask decomposition can be done (1) by LLM with simple prompting like "Steps for XYZ.\\n1.", "What are the subgoals for achieving XYZ?", (2) by using task-specific instructions; e.g. "Write a story outline." for writing a novel, or (3) with human inputs.'), Document(id='a536873c-7abd-41e7-9b5f-53dc1ebe4198', metadata={'source': 'http://lilianweng.github.io//posts/2023-06-23-agent/'}, page_content='The AI assistant can parse user input to several tasks: [{"task": task, "id", task_id, "dep": dependency_task_ids, "args": {"text": text, "image": URL, "audio": URL, "video": URL}}]. The "dep" field denotes the id of the previous task which generates a new resource that the current task relies on. A special tag "-task_id" refers to the generated text image, audio and video in the dependency task with id as task_id. The task MUST be selected from the following options: {{ Available Task List }}. There is a logical relationship between tasks, please note their order. If the user input can\'t be parsed, you need to reply empty JSON. Here are several cases for your reference: {{ Demonstrations }}. The chat history is recorded as {{ Chat History }}. From this chat history, you can find the path of the user-mentioned resources for your task planning.'), Document(id='424ff333-58f5-4d6f-9c20-97f8ced11458', metadata={'source': 'http://lilianweng.github.io//posts/2023-06-23-agent/'}, page_content='Fig. 11. Illustration of how HuggingGPT works. (Image source: Shen et al. 2023)\nThe system comprises of 4 stages:\n(1) Task planning: LLM works as the brain and parses the user requests into multiple tasks. There are four attributes associated with each task: task type, ID, dependencies, and arguments. They use few-shot examples to guide LLM to do task parsing and planning.\nInstruction:')],
'answer': 'Task Decomposition is a process where hard tasks are broken down into smaller and simpler steps. Techniques like Chain of Thought (CoT) and Tree of Thoughts play an important role in this respect. CoT prompts the model to think step by step, thereby transforming large tasks into multiple manageable ones. On the other hand, Tree of Thoughts expands on CoT and explores multiple reasoning paths at each step, creating a tree-like structure through which search processes like breadth-first search or depth-first search can be conducted. Decomposition can be achieved using language learning models with simple prompting, utilizing task-specific instructions, or with human inputs. The AI assistant is capable of parsing user input into several tasks, each with its own id, dependencies, and arguments.'}
"""
# 我们要的结果是print(response['answer'])
一般情况下,我们构建的链直接使用输入问题答案记录来关联上下文,但在此案例中,查询检索器也需要对话上下文才能被理解
解决办法:
添加一个子链,它采用最新用户问题和聊天历史,并在它引用历史信息中任何信息时重新表述问题,这可以被简单地认为是构建一个新的历史感知的检索器
这个子链的目的:让检索过程融入了对话的上下文
完整的RAG对话
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain.chains.history_aware_retriever import create_history_aware_retriever
from langchain.chains.retrieval import create_retrieval_chain
from langchain_chroma import Chroma
from langchain_community.document_loaders import WebBaseLoader
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables import RunnableWithMessageHistory
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.chat_message_histories import ChatMessageHistory
import os
import bs4key = ''
os.environ["OPENAI_API_KEY"] = key
model = ChatOpenAI(model='gpt-4')# 1.加载数据:一篇博客内容数据
# web_paths 爬取内容的url地址,可以一次性写多个
loader = WebBaseLoader(web_paths=['http://lilianweng.github.io//posts/2023-06-23-agent/'],bs_kwargs=dict(parse_only=bs4.SoupStrainer(class_=('post-header', 'post-title', 'post-content')) # class_这个是html页面的类选择器)
)
desc = loader.load() # 将博客内容解析出来
# 2.大文本切割
splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=20)# 切割documents对象,切文本用split_text,传入字符串
res = splitter.split_documents(desc)# 3.存储
vectorstore = Chroma.from_documents(documents=res, embedding=OpenAIEmbeddings())# 4.检索器
retriever = vectorstore.as_retriever()# 5.整合# 6.创建一个问题的模版system_prompt = """
You are an assistant for question-answering tasks.Use the following pieces of
retrieved context to answer the question.If you don't know how to answer say that you don't know
Use the sentences maximum and keep the answer concise.\n{context}
"""prompt = ChatPromptTemplate.from_messages([('system', system_prompt),MessagesPlaceholder("chat_history"), # 提问的历史记录('human', '{input}')
])# 7.得到chain
# 提问的chain
chain_one = create_stuff_documents_chain(model, prompt)# 创建一个子链
# 1.子链的提示模版
contextualize_q_system_prompt = """Given a chat history and the latest user question
which might reference context in the chat history,
formulate a standalone question which can be understood
without the chat history.Do not answer the question,
just reformulate it if needed and otherwise return it as is.
"""
retriever_history_temp = ChatPromptTemplate.from_messages([('system', contextualize_q_system_prompt),MessagesPlaceholder("chat_history"),('human', '{input}')
])
# 2.创建子链
history_chain = create_history_aware_retriever(model, retriever, retriever_history_temp)# 保存问答的历史记录
store = {}def get_session_history(session_id):if session_id not in store:store[session_id] = ChatMessageHistory()return store[session_id]# 创建一个父链:把前两个链整合
chain = create_retrieval_chain(history_chain, chain_one)result_chain = RunnableWithMessageHistory(chain,get_session_history,input_messages_key='input',history_messages_key='chat_history',output_messages_key='answer'
)# 第一轮
res_1 = result_chain.invoke({'input': 'What is Task Decomposition?'},config={'configurable': {'session_id': '123456'}}
)
print(res_1['answer'])# 第二轮
res_2 = result_chain.invoke({'input': 'What are common ways of doing it?'},config={'configurable': {'session_id': '123456'}}
)
print(res_2['answer'])# 第三轮,问一个跟文档没有关联的
res_3 = result_chain.invoke({'input': 'li si?'},config={'configurable': {'session_id': '123456'}}
)
print(res_3['answer'])
# 不想关的内容AI无法回答出来
# I'm sorry, but the question or phrase "li si" is unclear. Could you provide more context or clarify what you're asking?
关于模版定义中最开始的user参数跟后面使用的human参数,专门查询了一下,因为是不同的,也好奇两者是否有区别,大模型解释如下
在使用类似LangChain这样的库构建聊天提示模板(ChatPromptTemplate)时,
user
和human
都是用来标识消息来源是用户的占位符,但在具体实现或库的版本中可能有不同的含义或用途。然而,在你提供的两个代码片段中,它们实际上代表了相似的概念,即表示用户输入的部分。
- 在第一个代码片段中,
('user', '{text}')
表示这条消息是由用户发送的,并且将使用{text}
作为该消息的实际内容。- 在第二个代码片段中,
('human', '{input}')
也是指由用户发出的消息,这里使用{input}
来表示用户的具体输入。通常情况下,这两个术语(
user
和human
)可以互换使用,特别是在不同的库或者不同的上下文中。但是在特定的库或框架中,可能会有一个首选的术语。例如,在某些框架中,可能统一使用user
来表示来自用户的输入,而其他一些框架可能偏好human
。如果你正在使用的库特别区分这两个术语,那么你应该参照该库的文档以了解它们之间的具体差异。因此,在你给出的例子中,如果没有特定的库文档说明二者之间的区别,我们可以假设它们在这里的意义相同,都是为了标记出这是用户提供的输入部分。实际使用时,应该根据所用工具或库的具体指南进行选择。如果存在疑问,查阅相关库的最新文档是最好的解决办法。
相关文章:
AI大模型学习(四): LangChain(三)
Langchain构建代理 语言模型本身无法执行动作,他们只能输出文本,代理是使用大型语言模型(LLM)作为推理引擎来确定要执行的操作以及这些操作的输入应该是什么,然后这些操作的结果可以反馈到代理中,代理将决定是否需要更多的操作,或者是否可以结束 例如:我们想要查询现在北京的…...
JavaScript函数-arguments的使用
在JavaScript编程语言中,函数是构建复杂逻辑和实现代码复用的关键组件。虽然现代JavaScript(尤其是ES6及之后版本)提供了更多灵活的方式来处理函数参数(如剩余参数、默认参数等),但arguments对象仍然是一个…...
C# 从基础神经元到实现在0~9数字识别
训练图片:mnist160 测试结果:1000次训练学习率为0.1时,准确率在60%以上 学习的图片越多,训练的时候越长(比如把 epochs*10 10000或更高时)效果越好 using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Windo…...
【每日八股】计算机网络篇(一):概述
OSI 的 7 层网络模型? OSI(Open Systems Interconnection,开放互联系统)是由国际标准化组织(ISO)提出的一种网络通信模型。 自上而下,OSI 可以被分为七层,分别是:应用层…...
Jupyter里面的manim编程学习
1.Jupyterlab的使用 因为我之前一直都是使用的vscode进行manim编程的,但是今天看的这个教程使用的是Jupyter,我也很是好奇这个manim在Jupyter这样的交互式下面会生成怎么样的效果,所以今天尝试了jupyter,并且对于两个进行比较和说…...
Web刷题之PolarDN(简单)
1.swp 考点:敏感文件、preg_match()函数绕过 什么是swp文件: vim中的swp即swap文件,在编辑文件时产生,它是隐藏文件。这个文件是一个临时交换文件,用来备份缓冲区中的内容。如果原文件名是data,那么swp文件…...
JVM 深入理解与性能优化
JVM(Java Virtual Machine,Java 虚拟机)是 Java 代码运行的核心,它负责 内存管理、类加载、字节码执行、垃圾回收(GC)和 JIT 编译。理解 JVM 有助于优化 Java 应用的性能,提高调试和排错能力。 …...
【人工智能】蓝耘智算平台盛大发布DeepSeek满血版:开创AI推理体验新纪元
📝个人主页🌹:Eternity._ 🌹🌹期待您的关注 🌹🌹 ❀ 蓝耘智算平台 蓝耘智算平台核心技术与突破元生代推理引擎快速入门:三步调用大模型接口,OpenAI SDK无缝兼容实战用例文…...
minio作为K8S后端存储
docker部署minio mkdir -p /minio/datadocker run -d \-p 9000:9000 \-p 9001:9001 \--name minio \-v /minio/data:/data \-e "MINIO_ROOT_USERjbk" \-e "MINIO_ROOT_PASSWORDjbjbjb123" \quay.io/minio/minio server /data --console-address ":90…...
关于 BK3633 上电时受串口 UART2 影响而无法启动的问题说明
1. 问题描述 BK3633 SDK 版本:BK3633_DesignKit_V06_2310 使用 BK3633 UART2 与指纹模块进行通讯,为了降低功耗,通过 GPIO 控制了指纹模块的供电电源。但每次给整个系统板子上电时,BK3633 很大概率会实际而无法正常运行程序&…...
运维Ansible面试题及参考答案
目录 简述 Ansible 的工作原理,它是如何实现对远程主机管理的? Ansible 是基于什么语言开发的?这门语言的特性对 Ansible 的功能实现有哪些帮助? 解释 Agentless 在 Ansible 中的含义,与基于 Agent 的自动化工具相比,优势体现在哪? Ansible 中的 Inventory 文件是什…...
Spring Boot 日志管理(官网文档解读)
摘要 本篇文章详细介绍了SpringBoot 日志管理相关的内容,文章主要参考官网文章的描述内容,并在其基础上进行一定的总结和拓展,以方便学习Spring Boot 的小伙伴能快速掌握Spring Boot 日志管理相关的内容。 日志实现方式 Sping Boot 的日志管…...
Svelte 最新中文文档教程(17)—— 生命周期钩子
前言 Svelte,一个语法简洁、入门容易,面向未来的前端框架。从 Svelte 诞生之初,就备受开发者的喜爱,根据统计,从 2019 年到 2024 年,连续 6 年一直是开发者最感兴趣的前端框架 No.1: Svelte 以…...
Windows 上源码安装 FastGPT
FastGPT 是一个强大的 AI RAG 平台,值得我们去学习了解。与常见的 Python 体系不同,Fast GPT 采用 Node.js/Next.js 平台(对于广大 JS 开发者或前端开发者比较亲切友好),安装或部署比较简单。虽然一般情况下推荐简单的…...
RT-Thread+STM32L475VET6——icm20608传感器
文章目录 前言一、板载资源二、具体步骤1.打开CubeMX进行配置1.1 使用外部高速时钟,并修改时钟树1.2 打开I2C3,参数默认即可(I2C根据自己需求调整)1.3 打开串口1.4 生成工程 2. 添加icm20608软件包3. 使能传感器,打开动态链接库4.…...
超高清大图渲染性能优化实战:从页面卡死到流畅加载
目录 问题背景:1.为什么大图会导致页面卡死?一、DOM树构建(HTML Parsing)二、 资源加载:下载完整图片文件(可能高达30MB)三、解码处理(Decoding & Rasterization)、四…...
基于javaweb的SpringBoot个人博客系统设计和实现(源码+文档+部署讲解)
技术范围:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论…...
轻量级日志管理平台Grafana Loki
文章目录 轻量级日志管理平台Grafana Loki背景什么是Loki为什么使用 Grafana Loki?架构Log Storage Grafana部署使用基于 Docker Compose 安装 LokiMinIO K8s集群部署Loki采集Helm 部署方式和案例 参考 轻量级日志管理平台Grafana Loki 背景 在微服务以及云原生时…...
SOME/IP--协议英文原文讲解12(完结)
前言 SOME/IP协议越来越多的用于汽车电子行业中,关于协议详细完全的中文资料却没有,所以我将结合工作经验并对照英文原版协议做一系列的文章。基本分三大块: 1. SOME/IP协议讲解 2. SOME/IP-SD协议讲解 3. python/C举例调试讲解 4.3 Compa…...
Linux 命令大全完整版(12)
Linux 命令大全 5. 文件管理命令 ln(link) 功能说明:连接文件或目录。语 法:ln [-bdfinsv][-S <字尾备份字符串>][-V <备份方式>][--help][--version][源文件或目录][目标文件或目录] 或 ln [-bdfinsv][-S <字尾备份字符串>][-V…...
AI学习第二,三天-Python基础
变量、运算符与数据类型详解 注释 在 Python 中,注释是用于增加代码可读性、解释代码功能但不会被程序执行的部分。 单行注释:使用 # 符号,从 # 开始到本行末尾的内容均为注释。例如: 收起 python # 这是一个单行注释ÿ…...
Nginx代理ElasticSearch
1、将ES的账号:密码通过Base64加密 假设账号密码如下: 账号:elastic密码:elastichuayunworld.com echo -n elastic:elastichuayunworld.com | base64 ZWxhc3RpYzplbGFzdGljQGh1YXl1bndvcmxkLmNvbQ2、在 Nginx 配置中传递认证信息 locatio…...
开源AI网络爬虫工具Crawl4AI
引言 在信息化时代,网络爬虫作为从互联网中提取信息的重要工具,扮演着至关重要的角色。Crawl4AI作为一款开源AI网络爬虫工具,凭借其功能强大和易用性,受到了广泛关注。本文将详细探讨Crawl4AI的定义、特点、优势,以及…...
实现 INFINI Console 与 GitHub 的单点登录集成:一站式身份验证解决方案
本文将为您详细解析如何通过 GitHub OAuth 2.0 协议,为 INFINI Console 实现高效、安全的单点登录(Single Sign-On, SSO)集成。通过此方案,用户可直接使用 GitHub 账户无缝登录 INFINI Console,简化身份验证流程&#…...
Linux系统安装MySQL5.7(其他版本类似)避坑指南
1.远程连接 在Linux系统安装好MySQL5.7数据库,不要以为就大功告成了后面还有大坑等着你踩了。宏哥这里介绍一下远程连接遇到的坑以及如何处理。由于征文要求安装环境教学除外宏哥这里就不介绍在Linux系统安装mysql数据库,有需要的可以自己百度一下。但是…...
新数据结构(12)——代理
什么是代理 在进行操作时有时不希望用户直接接触到目标,这时需要使用代理让用户间接接触到目标 给目标对象提供一个代理对象,并且由代理对象控制着对目标对象的引用 图解: 代理的目的 控制访问:通过代理对象的方式间接的访问目…...
VLM(视觉语言模型)与DeepSeek R1(奖励机制)如何结合
VLM(视觉语言模型)与DeepSeek R1(奖励机制)如何结合 flyfish VLM的传统训练依赖于监督学习(直接拟合问答对),而规则奖励函数通常用于强化学习(通过试错和奖励反馈优化策略…...
问题:Flask应用中的用户会话(Session)管理失效
我来分享一个常见的PythonWeb开发问题: 问题:Flask应用中的用户会话(Session)管理失效 这是一个在Flask开发中经常遇到的问题。当用户登录后,有时会话会意外失效,导致用户需要重复登录。 解决方案: 1. 首先&#x…...
Qt/C++面试【速通笔记一】
Qt 信号与槽机制 什么是信号(Signal)和槽(Slot)? 在Qt中,信号(Signal)和槽(Slot)是实现对象之间通信的一种机制。信号是对象在某些事件发生时发出的通知&…...
RoCBert:具有多模态对比预训练的健壮中文BERT
摘要 大规模预训练语言模型在自然语言处理(NLP)任务上取得了最新的最优结果(SOTA)。然而,这些模型容易受到对抗攻击的影响,尤其是对于表意文字语言(如中文)。 在本研究中࿰…...
DeepSeek入门到大师 清华大学[1-5版]全集
1、文件概览 1、清华大学《DeepSeek:从入门到精通》 2、清华大学《Deepseek如何赋能职场应用?》 3、清华大学《普通人如何抓住DeepSeek红利》 4、清华大学《DeepSeekDeepResearch让科研像聊天一样简单》 5、清华大学《DeepSeek与AI幻觉》 6、天津大学《深度解读Deepseek:原理…...
Debezium:实时数据捕获与同步的利器
一、什么是 Debezium Debezium 是一个开源的分布式平台,专门用于捕获数据库中的数据变更。它通过读取数据库的事务日志,能够以非侵入性的方式捕获数据库中发生的所有变化,并将这些变化转化为事件流,实时推送到像 Kafka 这样的消息…...
【蓝桥杯】第十五届省赛大学真题组真题解析
【蓝桥杯】第十五届省赛大学真题组真题解析 一、智能停车系统 1、知识点 (1)flex-wrap 控制子元素的换行方式 属性值有: no-wrap不换行wrap伸缩容器不够则自动往下换行wrap-reverse伸缩容器不够则自动往上换行 (2࿰…...
AI助力下的PPT革命:DeepSeek 与Kimi的高效创作实践
清华大学出品《DeepSeek:从入门到精通》分享 在忙碌的职场中,制作一份高质量的PPT往往需要投入大量时间和精力,尤其是在临近截止日期时。今天,我们将探索如何借助 AI 工具 —— DeepSeek 和 Kimi —— 让 PPT 制作变得既快捷又高…...
【MySQL篇】持久化和非持久化统计信息的深度剖析(含analyze命令和mysqlcheck工具两种收集方式)
💫《博主介绍》:✨又是一天没白过,我是奈斯,从事IT领域✨ 💫《擅长领域》:✌️擅长阿里云AnalyticDB for MySQL(分布式数据仓库)、Oracle、MySQL、Linux、prometheus监控;并对SQLserver、NoSQL(…...
C++ 手撕定时器
C 手撕定时器 思路与知识调用场景类声明 参考 思路与知识 1. 为了支持相同时间戳下多个任务,需要考虑到支持重复key的std::mutimap, 以及成员函数equal_range 2. 工具函数Timer::GetTick 返回一个uint64_t毫秒时间戳作为multimap的key,需要会使用chrono…...
邮件安全之发件人伪造
电子邮件工作原理 电子邮件传输过程中主要涉及到SMTP、IMAP、POP3三种协议,具体功能如下: SMTP:全称Simple Mail Transfer Protocol,即简单邮件传输协议,主要用于发送邮件,使用端口号25。 IMAP:全称Internet Mail Acce…...
前端八股——JS+ES6
前端八股:JSES6 说明:个人总结,用于个人复习回顾,将持续改正创作,已在语雀公开,欢迎评论改正。...
Qt QTreeWidget 总结
Qt QTreeWidget 总结 1. 概述 QTreeWidget 是 Qt 中用于显示树形结构的控件,继承自 QTreeView,但提供了更简单的接口。适合展示层级数据(如文件目录、组织结构)。每个节点是 QTreeWidgetItem 对象,支持文本、图标、复…...
Python常见面试题的详解16
1. 如何强行关闭客户端和服务器之间的连接? 在网络编程中,有时需要强行中断客户端和服务器之间的连接。对于基于 TCP 协议的连接,由于其面向连接的特性,需要采取特定的步骤来确保连接被正确关闭;而 UDP 是无连接协议&a…...
前端设计模式面试题及参考答案
目录 如何用闭包实现单例模式?列举两种实现方式 工厂模式与构造函数创建对象的核心区别是什么? 抽象工厂模式如何解决多平台 UI 组件兼容问题? 原型模式在前端框架中如何优化对象创建性能? 建造者模式如何实现复杂表单配置的链式调用? 单例模式在全局状态管理中的典型…...
Python Django系列—入门实例(二)
数据库配置 现在,打开 mysite/settings.py 。这是个包含了 Django 项目设置的 Python 模块。 默认情况下, DATABASES 配置使用 SQLite。如果你是数据库新手,或者只是想尝试 Django,这是最简单的选择。SQLite 包含在 Python 中…...
STM32-智能台灯项目
一、项目需求 1. 红外传感器检测是否有人,有人的话实时检测距离,过近则报警;同时计时,超过固定时间则报警; 2. 按键 1 切换工作模式:智能模式、按键模式、远程模式; 3. 智能模式下,根…...
HTML之JavaScript DOM操作元素(2)
HTML之JavaScript DOM操作元素(2) 4.增删元素var element document.createElement("元素名") 创建新元素父元素.appendChild(子元素) 在父元素中追加子元素父元素.insertBefore(新元素,参照元素) 在特定元素之前新增元…...
智能优化算法:莲花算法(Lotus flower algorithm,LFA)介绍,提供MATLAB代码
一、 莲花算法 1.1 算法原理 莲花算法(Lotus flower algorithm,LFA)是一种受自然启发的优化算法,其灵感来源于莲花的自清洁特性和授粉过程。莲花的自清洁特性,即所谓的“莲花效应”,是由其叶片表面的微纳…...
【复习】计算机网络
网络模型 OSI 应用层:给应用程序提供统一的接口表示层:把数据转换成兼容另一个系统能识别的格式会话层:负责建立、管理、终止表示层实体之间的通信会话传输层:负责端到端的数据传输网络层:负责数据的路由、转发、分片…...
【R语言】读取CSV数据时,显示[1] PK...<0 行> (或0-长度的row.names)
一、问题 当我使用以下代码读取CSV数据后,发现使用head(data)显示[1] PK...<0 行> (或0-长度的row.names),如下截图所示。 # 尝试读取文件 data <- read.csv("C:\\Users\\11300\\Desktop\\test.csv", header TRUE) # 检查数据 hea…...
CentOS环境变量配置+解析
环境变量的作用就是让系统快速通过你的命令找到你的可执行程序,windows系统里也同理,也就是你每次输入个命令,系统就会找环境变量里到底有没有叫这个命令进程的 一、环境变量配置 1.编辑配置文件 vim /etc/profile export PATH$PATH:$JAVA…...
最新版本Exoplayer扩展FFmpeg音频软解码保姆级教程
ExoPlayer 是一个开源的 Android 媒体播放库,由 Google 开发和维护,用于替代 Android 系统自带的 MediaPlayer。它提供了更强大的功能、更好的性能和更高的灵活性,适用于各种复杂的媒体播放场景。所以被广泛用于各种播放器场景。 最近项目中…...
【蓝桥杯集训·每日一题2025】 AcWing 6134. 哞叫时间II python
6134. 哞叫时间II Week 1 2月20日 农夫约翰正在试图向埃尔茜描述他最喜欢的 USACO 竞赛,但她很难理解为什么他这么喜欢它。 他说「竞赛中我最喜欢的部分是贝茜说『现在是哞哞时间』并在整个竞赛中一直哞哞叫」。 埃尔茜仍然不理解,所以农夫约翰将竞赛…...