站长之家网站介绍,彩页设计图片模板,潍坊信息网网站建设,论坛网站方案路径#xff1a;agent-rag-微调 一.大模型应用发展及Agent前沿技术趋势 大模型有两个关键概念#xff1a;原生能力和涌现能力。 涌现能力#xff1a;这一能力指的是#xff0c;尽管大模型可能没有直接学习过某些信息#xff0c;但在与它对话时提供相关信息后#xff0c;它…路径agent-rag-微调 一.大模型应用发展及Agent前沿技术趋势 大模型有两个关键概念原生能力和涌现能力。 涌现能力这一能力指的是尽管大模型可能没有直接学习过某些信息但在与它对话时提供相关信息后它能够类比和推理出解决方案。 存在着两个主要问题知识库更新不及时和大模型幻觉问题。
步骤 Stage 1 提示工程 Stage 2函数调用解决了知识库更新不及时、无法获取实时信息及其带来的优势。 Stage 3. Retrieval-Augmented Generation RAG的实现是包括两个阶段的检索阶段和生成阶段。 RAG技术解决的两个关键的问题是 1.删去无用的上下文 2.token长度有限制
后续AI AGENTS,强化学习 AGENT架构规划记忆行动工具
二.AI Agent应用类型及Function Calling开发实战 分类聊天机器人、人工智能助手能管理家中的智能设备和人工智能代理能自主执行多种任务、做出决策和解决问题并且能够与现实世界互动
1.聊天机器人可以构建非常简单的While循环来生成一个持续对话的交互程序代码如下所示 from openai import OpenAI client OpenAI()
while True: prompt input(\n用户提问) if prompt 退出: break # 如果输入的是“退出”则结束循环 completion client.chat.completions.create( modelgpt-4o-mini, messages[{role: user, content: prompt}], max_tokens1024, temperature0.8) message completion.choices[0].message.content print(f模型回复:{message})
问题单个大模型并不具备记忆和状态跟踪的能力它仅将每个输入视为一个独立的事件来处理。 我们需要将每次的对话和大模型的回复 不断地追加到传递给 API 的消息字典列表中 from openai import OpenAI client OpenAI()
# 创建一个会话列表来不断地追加历史对话纪律 messages []
while True: prompt input(\n用户提问 ) if prompt 退出: break # 如果输入的是“退出”则结束循环 messages.append( { role:user, content:prompt }) completion client.chat.completions.create( modelgpt-4o-mini, messages messages) response completion.choices[0].message.content print(f模型回复:{response}) messages.append( { role:assistant, content:response })
当然为了解决大模型知识的局限性问题我们经常采用RAG技术来增强其信息检索能力。 RAG解决的问题输入较少的文本去prompt ChatGPT 不记得您之前的问题。因此为了与它进行有意义的对话您需要将对话反馈给 API。还记得需要传递给 API 的字典列表吗 messages []
while True: prompt input(\n提出一个问题 ) if prompt 退出: break # 如果输入的是“退出”则结束循环 messages.append( { role:user, content:prompt }) completion client.chat.completions.create( modelgpt-4o-mini, messages messages) response completion.choices[0].message.content print(response) messages.append( { role:assistant, content:response })
存在的问题是 输出 无法给到下游 要解决的根本两点问题就是
如何让 大模型产生结构化的输出 如何让 大模型在一次对话中自动执行多个步骤。
2.人工智能助手 起到的主要作用是替代手工执行特定的任务。 类似智能客服的整个问答流程涉及两个阶段第一阶段是接收用户的输入去查询数据库。第二阶段是根据数据库返回的结果结合用户的问题生成最终的答案。而这样的阶段性操作其根本要解决的两点问题是 如何让 大模型产生结构化的输出 如何让 大模型在一次对话中自动执行多个步骤。
使用大语言模型LLM通过API进行功能调用的完整生命周期。具体过程如下 a.API调用应用程序向API发送调用请求附带具体的提示信息和可供LLM调用的函数定义。(用的什么模型传递什么信息有哪些工具可以调用 b.模型决策LLM评估接收到的输入并决定是否直接回应用户或是需要调用一个或多个外部函数以提供更合适的回答。 c.API响应API向应用程序返回响应指明需要执行的函数以及执行这些函数所需的参数。 d.执行函数应用程序根据API的指示执行指定的函数使用提供的参数。 e.调用结果处理完成函数执行后应用程序再次调用API传递先前的提示信息和函数执行的结果以便LLM可以利用这些新数据生成最终的用户响应。 接下来实操一个智能客服的案例来详细介绍中间环节的详细处理流程。 首先我们先构造一个商家后台商品信息的模拟数据。这里使用 Python 连接 sqlite3库进行存储。代码如下所示 import sqlite3
def create_and_populate_database(): # 连接到本地数据库文件 conn sqlite3.connect(SportsEquipment.db) # 指定文件名来保存数据库 cursor conn.cursor() # 检查是否存在名为 products 的表如果不存在则创建 cursor.execute(SELECT name FROM sqlite_master WHERE typetable AND nameproducts;) if cursor.fetchone() is None: # 创建表 cursor.execute( CREATE TABLE products ( product_id TEXT, product_name TEXT, description TEXT, specifications TEXT, usage TEXT, brand TEXT, price REAL, stock_quantity INTEGER ) ) # 数据列表用于插入表中 products [ (001, 足球, 高品质职业比赛用球符合国际标准, 圆形直径22 cm, 职业比赛、学校体育课, 耐克, 120, 50), (002, 羽毛球拍, 轻量级适合初中级选手提供优秀的击球感受, 碳纤维材质重量85 g, 业余比赛、家庭娱乐, 尤尼克斯, 300, 30), (003, 篮球, 室内外可用耐磨耐用适合各种天气条件, 皮质标准7号球, 学校、社区运动场, 斯伯丁, 200, 40), (004, 跑步鞋, 适合长距离跑步舒适透气提供良好的足弓支撑, 多种尺码透气网布, 长跑、日常训练, 阿迪达斯, 500, 20), (005, 瑜伽垫, 防滑材料厚度适中易于携带和清洗, 长180cm宽60cm厚5mm, 瑜伽、普拉提, 曼达卡, 150, 25), (006, 速干运动衫, 吸汗快干适合各种户外运动持久舒适, S/M/L/XL多色可选, 运动、徒步、旅游, 诺斯脸, 180, 60), (007, 电子计步器, 精确计步带心率监测功能蓝牙连接手机应用, 可充电续航7天, 日常健康管理、运动, Fitbit, 250, 15), (008, 乒乓球拍套装, 包括两只拍子和三个球适合家庭娱乐和业余训练, 标准尺寸拍面防滑处理, 家庭、社区, 双鱼, 160, 35), (009, 健身手套, 抗滑耐磨保护手部适合各种健身活动, 多种尺码通风设计, 健身房、户外运动, Under Armour, 120, 50), (010, 膝盖护具, 减少运动伤害提供良好的支撑和保护适合篮球和足球运动, 弹性织物可调节紧度, 篮球、足球及其他运动, 麦克戴维, 220, 40) ] # 插入数据到表中 cursor.executemany( INSERT INTO products (product_id, product_name, description, specifications, usage, brand, price, stock_quantity) VALUES (?, ?, ?, ?, ?, ?, ?, ?) , products) # 提交更改以确保数据被保存在文件中 conn.commit() # 检索并打印所有记录以验证插入 cursor.execute(SELECT * FROM products) all_rows cursor.fetchall() conn.close() # 关闭连接以释放资源 return all_rows
# 执行函数并打印结果 create_and_populate_database()
第一步构建大模型能够调用的函数
import sqlite3
def query_by_product_name(product_name): # 连接 SQLite 数据库 conn sqlite3.connect(SportsEquipment.db) cursor conn.cursor() # 使用SQL查询按名称查找产品。%符号允许部分匹配。 cursor.execute(SELECT * FROM products WHERE product_name LIKE ?, (% product_name %,)) # 获取所有查询到的数据 rows cursor.fetchall() # 关闭连接 conn.close() return rows
第 二 步向大模型描述这个函数以便大模型知道如何调用它以及在什么情况下需要调用它 需要我们进一步创建一个“函数定义”来向模型描述该函数。该定义描述了该函数的作用以及可能何时调用该函数以及调用该函数需要哪些参数。 { name: query_by_product_name, description: Query the database to retrieve a list of products that match or contain the specified product name. This function can be used to assist customers in finding products by name via an online platform or customer support interface., # 查询数据库以检索匹配或包含指定产品名称的产品列表。此功能可用于帮助客户通过在线平台或客户支持界面按名称查找产品。 parameters: { type: object, properties: { product_name: { type: string, description: The name of the product to search for. The search is case-insensitive and allows partial matches. } }, required: [product_name] } } 这段Json Schema 描述的关键要素如下
name 字段明确指示大模型需要调用的具体函数名称。 description 字段向大模型说明在哪些用户需求下应当触发这个函数即在何种场景下调用。 parameters详细描述函数所接受的参数使大模型能够从类似“你家都卖什么球”的自然语言查询中提取出“球”作为关键搜索词。其中的required字段指明哪些参数是必需的确保函数能在缺少这些参数时提示或防止执行。
第 三 步将函数定义作为可用工具以及消息传递给大模型 当涉及到函数调用的时候我们需要在调用聊天完成 API 时额外的传递一个 tools参数以告知大模型你在当前的会话过程中可以调用query_by_product_name参数。 tools [ { type: function, function: { name: query_by_product_name, description: Query the database to retrieve a list of products that match or contain the specified product name. This function can be used to assist customers in finding products by name via an online platform or customer support interface., parameters: { type: object, properties: { product_name: { type: string, description: The name of the product to search for. The search is case-insensitive and allows partial matches. } }, required: [product_name] } } } ] 然后 from openai import OpenAI client OpenAI()
response client.chat.completions.create( modelgpt-4o-mini, messagesmessages, toolstools, # 这里是添加 )
第 四 步 接收并处理大模型响应 这里需要注意的是尽管传递了 tools工具但并不意味着大模型一定会进行调用 假设用户的问题中提及了关于商品的提问才会触发工具调用的流程 messages [ {role: user, content: 你好你家都卖什么球} ] response client.chat.completions.create( modelgpt-4o-mini, messagesmessages, toolstools, )
response 返回值为ChatCompletion(idchatcmpl-A6aaHkwifCmRmxPOKVkVQc5yppiY9, choices[Choice(finish_reasontool_calls, index0, logprobsNone, messageChatCompletionMessage(contentNone, refusalNone, roleassistant, function_callNone, tool_calls[ChatCompletionMessageToolCall(idcall_6Axa00hfMAVSzSGEBMIjXFZw, functionFunction(arguments{product_name:球}, namequery_by_product_name), typefunction)]))], created1726133961, modelgpt-4o-mini-2024-07-18, objectchat.completion, service_tierNone, system_fingerprintfp_483d39d857, usageCompletionUsage(completion_tokens17, prompt_tokens109, total_tokens126)) 这里的区别是当触发函数调用content字段的对应的值将会是None而tool_calls字段中的内容将会按照我们对query_by_product_name的Json Schema描述中 required字段的要求来返回值。如上所示为arguments{product_name:球}, namequery_by_product_name)。当拿到这样的参数后按照我们期望的逻辑应该是把球作为关键词执行数据库查询拿到商品的详细信息如下图所示 tool_call response.choices[0].message.tool_calls[0] arguments json.loads(tool_call.function.arguments) product_name arguments.get(product_name) final_res query_by_product_name(product_name) 得到含球字的那些字段
第 五 步将函数调用结果提供回大模型 经过上面的手动流程现在我们已经在本地执行了函数调用我们需要将此函数调用的结果提供回聊天 API以便大模型可以生成用户应该看到的实际响应。参考聊天机器人案例中构建大模型记忆的过程我们只需要维护一个 message 列表把函数调用的信息追加进去即可。整个过程如下所示 这里我们需要在使用 json.dumps() 添加 ensure_asciiFalse 参数。这样JSON 库就会保留中文字符而不是将它们转换为 Unicode 转义序列如下所示 content json.dumps({ product_name: product_name, query_by_product_name:final_res }, ensure_asciiFalse),
# 创建 function calling 结果的消息历史 function_call_result_message {role: tool, content: str(content), tool_call_id: response.choices[0].message.tool_calls[0].id}
接下来我们把这个能够调用外部工具的助手再次以聊天机器人的形式来实现。最终封装代码如下 from openai import OpenAI client OpenAI()
messages []
while True: prompt input(\n提出一个问题 ) if prompt.lower() 退出: break # 如果输入的是“退出”则结束循环 # 添加用户的提问到消息列表 messages.append({role: user, content: prompt}) # 检查是否需要调用外部函数 completion client.chat.completions.create( modelgpt-4o-mini, messagesmessages, toolstools, parallel_tool_callsFalse # 这里需要格外注意 ) # 提取回答内容 response completion.choices[0].message tool_calls completion.choices[0].message.tool_calls # 处理外部函数调用 if tool_calls: function_name tool_calls[0].function.name function_args json.loads(tool_calls[0].function.arguments) function_response available_functions[function_name](**function_args) messages.append(response) messages.append( { role: tool, name: function_name, content: str(function_response), tool_call_id: tool_calls[0].id, } ) second_response client.chat.completions.create( modelgpt-4o-mini, messagesmessages, ) # 获取最终结果 final_response second_response.choices[0].message.content messages.append({role: assistant, content: final_response}) print(final_response) else: # 打印响应并添加到消息列表 print(response.content) messages.append({role: assistant, content: response.content})
存在的问题无法接受并行输入比如同时问几个东西也就是parallel_tool_callsFalse 这句。 3. 并行函数调用 默认情况下在OpenAI 的大模型生态中2023 年 11 月 6 日或之后发布的任何模型都可能在单个响应中生成多个函数调用这说明这类模型可以并行调用某个函数。 我们可以先打印结果看一下 for tool_call in response.choices[0].message.tool_calls: print(tool_call)
结果ChatCompletionMessageToolCall(idcall_lMhDOkgreD5ogxG8byFgXRo9, functionFunction(arguments{product_name: 球}, namequery_by_product_name), typefunction) ChatCompletionMessageToolCall(idcall_t9i9HNvhmNSZaa3U454uBWxS, functionFunction(arguments{product_name: 衣服}, namequery_by_product_name), typefunction) ChatCompletionMessageToolCall(idcall_PxcU5AWYGEdUFUwy7iDs8Gfa, functionFunction(arguments{product_name: 鞋}, namequery_by_product_name), typefunction) 其中tool_calls 数组中的每个函数调用都有一个唯一的id 而如果我们想在单次的对话中记录每个函数调用的结果就可以通过向每个函数调用的对话添加一条新消息来将结果提供回模型每条消息都包含一个函数调用的结果并使用tool_call_id引用来自的id tool_calls 如下所示 product_info {}
# 遍历工具调用处理每一个产品名称查询 for tool_call in response.choices[0].message.tool_calls: # 解析调用参数 arguments json.loads(tool_call.function.arguments) product_name arguments[product_name] # 执行查询并获取结果 query_results query_by_product_name(product_name) messages.append({role: tool, content: str(query_results), tool_call_id: tool_call.id}) # 格式化输出到字典 query_results 返回的列表中包含完整的产品信息 # 提取所需信息假设每个结果包含 product_name, description, price 等字段 if query_results: for result in query_results: product_id, name, description, specifications, usage, brand, price, stock result product_info[name] { 描述: description, 规格: specifications, 适用场合: usage, 品牌: brand, 价格: f{price}元, 库存数量: stock } else: product_info[product_name] 未找到相关产品数据
# 打印整理好的产品信息字典 for product_name, details in product_info.items(): print(f产品名称{product_name}) if isinstance(details, dict): for detail_key, detail_value in details.items(): print(f{detail_key}: {detail_value}) else: print(details) print() # 用于在每个产品信息之后添加一个空行以提高可读性
4.多函数调用 多函数调用其实就不是很复杂了。我们只需要新增函数并且编写具体的函数说明就可以了。比如我们现在接入智能电商客服的第二个功能可以根据用户对商品的提问查询对应的优化政策那么接下来我们定义一个read_store_promotions函数根据提供的产品名称来读取具体的优惠政策。代码如下 def read_store_promotions(product_name): # 指定优惠政策文档的文件路径 file_path store_promotions.txt try: # 打开文件并按行读取内容 with open(file_path, r, encodingutf-8) as file: promotions_content file.readlines() # 搜索包含产品名称的行 filtered_content [line for line in promotions_content if product_name in line] # 返回匹配的行如果没有找到返回一个默认消息 if filtered_content: return .join(filtered_content) else: return 没有找到关于该产品的优惠政策。 except FileNotFoundError: # 文件不存在的错误处理 return 优惠政策文档未找到请检查文件路径是否正确。 except Exception as e: # 其他潜在错误的处理 return f读取优惠政策文档时发生错误: {str(e)} 存在的问题如果同时需要并行和多函数调用则并行就出不来了 解决需要ai agent框架