花一点时间继续写下,RAG结合LLM。通过上一篇文章你应该知道为什么RAG要结合LLM,或者说为什么LLM要结合RAG使得LLM更强大,特别是当LLM 应用在人机对话等方面的时候。只要涉及一问一答,并通过上下文继续丰富对话,就会涉及到他。这个是看事情的两个维度。就像是买钟送电池还是买电池送闹钟。一方面,RAG的专家知识库上因为加入了LLM,而使得RAG对应更自然,不再是生硬的回答,借助LLM,可以帮助RAG的回答润色。另一方面,LLM因为专业知识的相对缺乏,毕竟是AIGC,不是垂直领域的AI,所以需要RAG帮忙加持,二者相互完善,彼此成就。好了,不太喜欢写虚的,直接开始干货分享。
在这两者结合的过程中,你要知道一件事,那就是LLM大模型必须知道你所提出的问题,在什么时候需要 LLM来回答, 什么时候需要 RAG 来回答,才是比较好的结果,prompt 起着至关重要的作用。他本质上会告诉LLM,这个问题由RAG来回答是比较好的,因为‘我’是这方面的领域专家。LLM怎么知道他是这方面领域的专家呢?就可以透过一些关键字来描述。当然prompt 的用处很多,很多书上会写他实际上会指导在客户描述的受限条件下,这里的受限条件,可以由prompt 来描述。比如 ‘如果你发现这类问题是医学相关的问题,请尝试使用我的RAG_Medcine 知识库做回答 ’。但在每个模型实现时,又有所差别。
我下面用通义千问 model 来进行举例说明,通过function式的调用如何实现RAG与LLM结合,并解释他是如何工作的,先附上完整代码:
from datetime import datetime import random import json import dashscope from dashscope import Generation dashscope.api_key = '需要自己去申请一个key' # 定义工具列表,模型在选择使用哪个工具时会参考工具的name和description tools = [ # 工具1 获取当前时刻的时间 { "type": "function", "function": { "name": "get_current_time", "description": "当你想知道现在的时间时非常有用。", "parameters": {} # 因为获取当前时间无需输入参数,因此parameters为空字典 } }, # 工具2 获取指定城市的天气 { "type": "function", "function": { "name": "get_current_weather", "description": "当你想查询指定城市的天气时非常有用。", "parameters": { # 查询天气时需要提供位置,因此参数设置为location "type": "object", "properties": { "location": { "type": "string", "description": "城市或县区,比如北京市、杭州市、余杭区等。" } } }, "required": [ "location" ] } } ] # 模拟天气查询工具。返回结果示例:“北京今天是晴天。” def get_current_weather(location): return f"{location}今天是晴天。 " # 查询当前时间的工具。返回结果示例:“当前时间:2024-04-15 17:15:18。“ def get_current_time(): # 获取当前日期和时间 current_datetime = datetime.now() # 格式化当前日期和时间 formatted_time = current_datetime.strftime('%Y-%m-%d %H:%M:%S') # 返回格式化后的当前时间 return f"当前时间:{formatted_time}。" # 封装模型响应函数 def get_response(messages): response = Generation.call( model='qwen-max', messages=messages, tools=tools, seed=random.randint(1, 10000), # 设置随机数种子seed,如果没有设置,则随机数种子默认为1234 result_format='message' # 将输出设置为message形式 ) return response def call_with_messages(): print('\n') messages = [ { "content": input('请输入:'), # 提问示例:"现在几点了?" "一个小时后几点" "北京天气如何?" "role": "user" } ] # 模型的第一轮调用 first_response = get_response(messages) assistant_output = first_response.output.choices[0].message print(f"\n大模型第一轮输出信息:{first_response}\n") messages.append(assistant_output) # 如果模型判断无需调用工具,则将assistant的回复直接打印出来,无需进行模型的第二轮调用 if 'tool_calls' not in assistant_output: print(f"最终答案:{assistant_output.content}") return # 如果模型选择的工具是get_current_weather elif assistant_output.tool_calls[0]['function']['name'] == 'get_current_weather': tool_info = {"name": "get_current_weather", "role": "tool"} location = json.loads(assistant_output.tool_calls[0]['function']['arguments'])['properties']['location'] tool_info['content'] = get_current_weather(location) # 如果模型选择的工具是get_current_time elif assistant_output.tool_calls[0]['function']['name'] == 'get_current_time': tool_info = {"name": "get_current_time", "role": "tool"} tool_info['content'] = get_current_time() print(f"工具输出信息:{tool_info['content']}\n") messages.append(tool_info) # 模型的第二轮调用,对工具的输出进行总结 second_response = get_response(messages) print(f"大模型第二轮输出信息:{second_response}\n") print(f"最终答案:{second_response.output.choices[0].message['content']}") if __name__ == '__main__': call_with_messages()
我们看看他的输出:
我们可以看到我们自己定义了专业的函数,这就相当于是 RAG,他的 "description": "当你想知道现在的时间时非常有用。" 为LLM指明了什么情况下 LLM 应该调用‘我’。当大模型发现需要调用‘我’RAG时,就会调用。同时我们将RAG生成的答案再经过一次LLM,他会在已有答案上进行之前我说的润色,得到最终答案。附上一个解释说明,你会更加明白:
时间有限,今天先写到这里,后面继续补充
标签:RAG,get,tool,实践,current,LLM,response From: https://blog.csdn.net/talentyiyy/article/details/139865098