视频链接:https://www.bilibili.com/video/BV1Hz421b7ag/?spm_id_from=333.788&vd_source=90787f5794c8e73cf358973d1de2e47f
# # 将.env的信息放到环境变量
# from dotenv import load_dotenv
# load_dotenv()''' 第一节课程:使用openai调用智谱轻言问答示例'''
from openai import OpenAI
client = OpenAI(api_key="你的key",base_url="https://open.bigmodel.cn/api/paas/v4/"
)completion = client.chat.completions.create(model = 'glm-4', # 使用的模型messages = [ # 对话列表{'role':'system','content':"你被用于抑制用户的购买欲望。当用户说要想买什么东西的时候,你需要提供理由让用户不要买。"},{'role':'user','content':"我正在考虑购买一个键盘,但我想抑制这个购买欲望。你能帮我列出一些理由,让我思考一下是否真的需要这个商品嘛?"}], max_tokens = 400, # max_tokens用于控制模型输出的长度,取值范围取决于模型和输入,模型有可以处理的token总数,输入和输出不能超过这个数量。像'glm-4'最多token数量为128ktemperature = 0.5 # temperature用于控制输出的随机性,数值越高随机性越大,每次都想得到一样的输出数值可以设置低一点
)print(completion.choices[0].message.content)# # ######################## 以下示例是一个应用完整的调用,主要由3部分组成:Prompt Template、Model、OutputParser######################################
from langchain_openai import ChatOpenAI
from langchain.prompts import ChatPromptTemplate# Prompt Template: 用于将Prompt不变的地方固定住,需要变的地方留空。
prompt_template = ChatPromptTemplate.from_messages([('system',"你被用于抑制用户的购买欲望。当用户说要想买什么东西的时候,你需要提供理由让用户不要买。"),('human',"我正在考虑购买一个{product},但我想抑制这个购买欲望。你能帮我列出一些理由,让我思考一下是否真的需要这个商品嘛?")]
)
prompt_template.format(product='球鞋')# Model:用于输入Prompt回答的模型
model = ChatOpenAI(model = 'glm-4',api_key="你的key",base_url="https://open.bigmodel.cn/api/paas/v4/",max_tokens = 500, # max_tokens用于控制模型输出的长度temperature = 0.7
)# OutputParser:进一步解析模型的输出变成所需要的样子,尤其是输出与需要的不一致时,解析过程可能会再次调用模型
def output_parser(output: str):parser_model = ChatOpenAI(model = 'glm-3-turbo',temperature = 0.2,api_key="你的key",base_url="https://open.bigmodel.cn/api/paas/v4/")message = "你需要将传入的文本改写,尽可能更自然,这是你需要改写的文本:{text}"return parser_model.invoke(message.format(text=output))# 其实在一开始的prompt中就要求回复自然的文本也是可以的。但在工程中,想获取稳定一致的输出,最好一个步骤只做一件事。
chain = prompt_template | model | output_parser # 这里建立一个完整的调用链
answer = chain.invoke(input={'product':'裤子'})
print(answer.content)# # # # 一个省钱助手 # # #
# chain = prompt_template | model | output_parser # 这里建立一个完整的调用流程
# while True:
# product = input("Hello! 马上要双十一,你最近又想买点啥?")
# answer = chain.invoke(input={'product':product})
# print(answer.content)''' 第二节课程:langchain添加memory'''
from langchain.prompts import ChatPromptTemplateprompt_template = ChatPromptTemplate.from_messages([('system',"You are a chatbot."),('human',"{new_messages}")]
)print(prompt_template.invoke({'new_messages':'Hello'}).messages)# # # 同样,传入历史消息也是留空一个位置
from langchain.prompts import MessagesPlaceholderprompt_template = ChatPromptTemplate.from_messages([('system',"You are a chatbot."),# ('system', "你是一个聊天机器人"),MessagesPlaceholder(variable_name="chat_history"),('human',"{new_messages}")]
)print(prompt_template.invoke({'chat_history':[('human','Hello'),('ai','Hi'),], 'new_messages':'How old are you?'}).messages)from langchain_openai import ChatOpenAImodel = ChatOpenAI(model = 'glm-3-turbo',api_key="你的key",base_url="https://open.bigmodel.cn/api/paas/v4/",max_tokens = 500, # max_tokens用于控制模型输出的长度temperature = 0.7
)# # 添加memory步骤:首先用prompt_template和model组成chain,然后定义列表来存储对话记录
chain = prompt_template | model
chat_history = []# 每次调用chain函数时,将传给模型的话和模型返回的话放入chat_history列表,下次调用的时候再作为历史信息传进去
def chat(new_messages):response = chain.invoke({'chat_history': chat_history, 'new_messages': new_messages})chat_history.extend([('human', new_messages),('ai', response.content)])return response.contentprint(chat('你好,我是ysn,今年72岁,已经退休了,正在学习AI知识'))
print(chat('请你阐述一下你了解关于我的个人信息'))# 在实际应用中用langchain的component来实现,对开发一致性和扩展性都更好
from langchain_community.chat_message_histories import ChatMessageHistorychat_history = ChatMessageHistory()chat_history.add_user_message('你好,我是ysn,今年72岁,已经退休正在学习AI知识')
chat_history.add_ai_message('你好,我是AI')from langchain_core.runnables.history import RunnableWithMessageHistorychain_with_memory = RunnableWithMessageHistory(chain,lambda x: chat_history,input_messages_key = 'new_messages',history_messages_key = 'chat_history'
)print(chain_with_memory.invoke({'new_messages': '请你阐述一下你了解关于我的个人信息'}, config={"configurable":{"session_id": "unused"}}).content)
print(chat_history.messages)# 这个函数接受传入chain的东西然后修剪记忆,再将传入chain的东西返回去。
def trim_messages(chain_input):'''修剪记忆'''stored_messages = chat_history.messages# 当大于两条时就清空记忆保留最后两条if len(stored_messages) > 2:chat_history.clear()for message in stored_messages[-2:]:chat_history.add_message(message)return chain_inputchain_with_trimming = trim_messages | chain_with_memoryprint(chain_with_trimming.invoke({'new_messages': '请你阐述一下你了解关于我的个人信息'}, config={"configurable":{"session_id": "unused"}}).content)
print(chat_history.messages)def summarize_messages(chain_input):'''总结记忆,需要调用模型来总结'''stored_messages = chat_history.messages# 当信息数大于等于6条时进行总结if len(stored_messages)>=6:summarization_prompt = ChatPromptTemplate.from_messages([MessagesPlaceholder(variable_name="chat_history"),("user","将上述聊天信息提炼为一条摘要信息。尽可能多的包含具体细节。")])summarization_chain = summarization_prompt | modelsummary_message = summarization_chain.invoke({"chat_history": stored_messages})chat_history.clear()chat_history.add_message(summary_message)return chain_inputchain_with_summarization = summarize_messages | chain_with_memorychat_history.clear()
chat_history.add_message(('human','你好,我是ysn,我今年72岁,已经退休正在学习AI知识'))
chat_history.add_message(('ai','你好,我是AI,请问有什么可以帮你'))
chat_history.add_message(('human','你觉得我适合做AI工程师嘛'))
chat_history.add_message(('ai','适合'))
chat_history.add_message(('human','为什么'))
chat_history.add_message(('ai','因为你在学习AI知识'))print(chain_with_summarization.invoke({'new_messages': '你觉得我适合干什么'}, config={"configurable":{"session_id": "unused"}}).content)
print(chat_history.messages)''' 第三节课程:Agent原理与快速构建'''
# agent 是一种结合了大模型推理能力和实际操作能力的智能体
# 通常我们使用模型是通过问答模式,比如我想实现数据库查询,模型可以告诉我一个Sql语句,然后需要自己粘贴这个语句到数据库中执行,来获取这个查询结果。
# agent 可以接受我们的自然语言,直接修改数据库,还可以上网查找资料,回答最近发生的事情。# 定义模型
from langchain_openai import ChatOpenAImodel = ChatOpenAI(model = 'glm-4-flash', # 完全免费且响应速度很快openai_api_base = "https://open.bigmodel.cn/api/paas/v4/",api_key="你的key",
)# 定义 tools
from langchain_community.tools import DuckDuckGoSearchRun # DuckDuckGo 搜索引擎免费# 操作数据库的 tool
import pandas as pd
from pandasql import sqldfdef simulate_database_operation(sql):my_table = pd.DataFrame({'name': ['Henry Myers', 'Martha Hawkins', 'Kelsey Lutz', 'Jonathan Fowler', 'Jonathan Young', 'Autumn Johnson', 'Kimberly Macias', 'Jared Mccormick', 'Casey Hoover', 'Erica Morse'],'age': [60, 44, 54, 46, 76, 22, 69, 33, 23, 35],'sex': ['F', 'M', 'M', 'F', 'F', 'M', 'M', 'F', 'F', 'M']})result = sqldf(sql)return result
# 正常的查询
print(simulate_database_operation('SELECT * FROM my_table WHERE age > 50'))
# # 错误的查询
# print(simulate_database_operation('SELECT * FROM my_table WHERE id > 50'))# 如何把函数包装成tool? 只要加装饰器和docstring(即使用说明)即可
from langchain.tools import tool@tool
def simulate_database_operation(sql: str):'''根据sql语句操作数据库'''my_table = pd.DataFrame({'name': ['Henry Myers', 'Martha Hawkins', 'Kelsey Lutz', 'Jonathan Fowler', 'Jonathan Young', 'Autumn Johnson', 'Kimberly Macias', 'Jared Mccormick', 'Casey Hoover', 'Erica Morse'],'age': [60, 44, 54, 46, 76, 22, 69, 33, 23, 35],'sex': ['F', 'M', 'M', 'F', 'F', 'M', 'M', 'F', 'F', 'M']})result = sqldf(sql)return result# 模型调用 tool
tools = [DuckDuckGoSearchRun(), simulate_database_operation]
model_with_tools = model.bind_tools(tools)from pprint import pprint as pp# 不需要调用tool的问题
response = model_with_tools.invoke('印度的首都是哪里?')
pp(dict(response))# 不需要调用tool的问题
search_response = model_with_tools.invoke('最近有什么新鲜事?搜索之后告诉我')
pp(dict(search_response))fetch_response = model_with_tools.invoke('现在是北京时间几点?查询之后告诉我')
pp(dict(fetch_response))# 需要操作数据库的问题
db_response = model_with_tools.invoke('帮我往数据库的my_table表中插入一条数据,name是张三,age是18,sex是male')
pp(dict(db_response))######################### 手动实现agent ################################
# from icecream import icdef call_tool(model_output, tools):tools_map = {tool.name.lower(): tool for tool in tools}tools_response = {}for tool in model_output.tool_calls:tool_name = tool['name']tool_args = tool['args']tool_instance = tools_map[tool_name]tool_response = tool_instance.invoke(*tool_args.values())tools_response[tool_name] = tool_responsereturn tools_responsedef manual_agent(query: str, model: ChatOpenAI, tools: list[tool]):'''①模型和工具绑定、②调用绑定的模型查询、③调用tool ④用tool_response和一开始的询问query获取最终的回答final_response'''model_with_tools = model.bind_tools(tools)model_output = model_with_tools.invoke(query)tool_response = call_tool(model_output, tools)final_response = model.invoke(f'original query: {query} \n\n\n tool response: {tool_response}',)return final_responseprint(manual_agent("帮我查询数据库my_table表中有多少人年龄大于60", model, tools).content)# 使用 langgraph 定义 agent
from langgraph.prebuilt import create_react_agent
agent = create_react_agent(model, tools)from langchain_core.messages import HumanMessageresponse = agent.invoke({'messages': [HumanMessage(content="帮我查询数据库my_table表中有多少人年龄大于60")]})
print(response)response = agent.invoke({'messages': [HumanMessage(content="今天在北京的天气怎么样")]})
print(response)