拓冰建站拓冰建站
首页 / 资讯中心 / 正文

在 Azure OpenAI 中集成函数调用(Function Calling):让生成式 AI 应用获得结构化输出与外部数据能力

在 Azure OpenAI 中集成函数调用Function Calling让生成式 AI 应用获得结构化输出与外部数据能力【免费下载链接】generative-ai-for-beginners21 Lessons, Get Started Building with Generative AI项目地址: https://gitcode.com/GitHub_Trending/ge/generative-ai-for-beginners本文基于本仓库第 11 课《Integrating with function calling》的内容撰写。该课程讲解了一个贯穿性的场景面向教育类创业公司构建一个能用自然语言帮用户检索技术课程的聊天机器人。读完本文后你将理解函数调用Function Calling要解决的两大问题响应格式不一致、无法接入外部数据掌握基于 Azure OpenAI Responses API / Chat Completions API 声明工具、执行函数、回填结果并生成自然语言答复的完整三步流程并能够把同样的模式复用到真实应用中查询数据库、调用第三方 API、生成结构化数据等。一、为什么需要函数调用两个核心痛点在函数调用出现之前LLM 的响应存在两个明显缺陷而这正是课程中构建“课程推荐聊天机器人”时首先需要克服的响应格式不一致。开发者向 LLM 提问时模型返回的是非结构化文本字段格式时好时坏。为了能兼容每一种返回变体开发者被迫编写大量校验代码。无法接入训练数据之外的信息。模型只能基于其训练截止日期之前的数据作答因此用户无法得到诸如“斯德哥尔摩现在的天气怎么样”这类需要实时外部数据支撑的答案。函数调用Function Calling正是 Azure OpenAI 服务针对上述两类限制提供的解决方案它可以带来两个关键收益一致的响应格式Consistent response format更好地控制模型输出结构方便下游系统直接消费结果外部数据接入External data把应用中其他数据源接入到对话上下文中。配套的可运行 Notebook 位于 11-integrating-with-function-calling/python/aoai-assignment.ipynb文中所有代码片段均可从中直接找到可执行版本。二、通过一个场景直观理解“响应格式问题”课程用一个具体例子来演示问题所在。假设要为教育产品建立学生档案库以便推荐合适的课程。我们准备了两位学生描述student_1_description与student_2_description数据内容非常相似再构造两条完全相同的提示词要求 LLM 从文本中提取name、major、school、grades、club字段并以 JSON 返回prompt1 f Please extract the following information from the given text and return it as a JSON object: name major school grades club This is the body of text to extract the information from: {student_1_description} 在完成 Azure OpenAI 客户端初始化后api_key、base_url指向endpoint/openai/v1/见 00-course-setup/03-providers.md 中的AZURE_OPENAI_API_KEY、AZURE_OPENAI_ENDPOINT、AZURE_OPENAI_DEPLOYMENT环境变量约定调用 Responses API 并解析返回openai_response1 client.responses.create( modeldeployment, input[{role: user, content: prompt1}], storeFalse, ) json_response1 json.loads(openai_response1.output_text)同样的提示词、相似的学生描述得到的 JSON 却出现了不一致// 响应 1 { name: Emily Johnson, major: computer science, school: Duke University, grades: 3.7, club: Chess Club } // 响应 2 { name: Michael Lee, major: computer science, school: Stanford University, grades: 3.8 GPA, club: Robotics Club }可以看到grades字段有时是3.7有时是3.8 GPA——这正是典型的“非结构化输入进、非结构化输出出”问题。如果这些数据要存入数据库或交给其他 API就必须保证字段格式可预期。函数调用如何解决问题函数调用的工作方式值得特别注意LLM 并不会真的去执行任何函数。相反我们为模型提供一份“函数结构说明”让它在回答时严格遵守随后由我们自己的应用代码读取这份结构化响应决定调用哪个真实函数。函数返回结果后再回传给 LLM由 LLM 用自然语言组织最终答复。图函数调用不负责执行函数只负责产出结构化的“调用意图”真正执行由应用完成结果再次回流给 LLM 生成最终答复。详见 11-integrating-with-function-calling/images/Function-Flow.png。三、函数调用的典型使用场景仓库课程正文与 Notebookoai-assignment.ipynb总结了三类最常见的应用模式调用外部工具Calling External Tools聊天机器人从用户消息中提取意图进而执行真实任务。例如学生说“给我导师发一封邮件告诉他这个主题我需要更多帮助”即可触发一个send_email(to: string, body: string)的函数调用。生成 API 或数据库查询Create API or Database Queries把自然语言转成格式化的查询或 API 请求。例如老师提问“哪些学生完成了最近一次作业”可映射到get_completed(student_name: string, assignment: int, current_status: string)这样的函数。生成结构化数据Creating Structured Data让 LLM 从一段文本或 CSV 中抽取要点。例如把维基百科的和平协议文章转成 AI 记忆卡可借助get_important_facts(agreement_name: string, date_signed: string, parties_involved: list)完成。四、创建你的第一个函数调用三个关键步骤整个函数调用流程可以归纳为三步对 Chat Completions API 是functions/function_call参数体系对 Responses API 是tools/tool_choice参数体系见仓库 Notebook 注释调用携带函数工具列表和用户消息调用模型 API读取解析模型返回的“调用意图”哪个函数、什么参数据此执行真实动作函数或外部 API再调用把函数执行结果再次提交给模型让它基于结果组织面向用户的回复。图函数调用三步骤示意。用户消息与函数定义作为上下文共同送入模型模型据此决策并产出结构化的函数调用请求。原始图见 11-integrating-with-function-calling/images/LLM-Flow.png。第 1 步创建用户消息第一步是构造一条用户消息。它可以来自文本框动态赋值也可以先写死一条便于测试。首次接触 Chat Completions / Responses API 时必须同时定义消息的role与content。role可以是system设定规则、assistant模型自身或user最终用户。函数调用场景下我们通常将输入角色设为usermessages [{role: user, content: Find me a good course for a beginner student to learn Azure.}]通过明确区分不同角色LLM 才能理解“是谁在说话”从而构建起可继续累积的对话历史。第 2 步声明函数及参数结构接下来定义函数清单。本文只使用一个search_courses函数但实际可以一次声明多个。课程特别提醒了一个容易被忽略的事实重要函数声明会随系统消息一起发送给 LLM并占用你可用的 token 配额。函数以对象数组的形式组织。在 Responses API 的扁平化格式中每个条目工具包含type、name、description与parameters顶层字段functions [ { type: function, name: search_courses, description: Retrieves courses from the search index based on the parameters provided, parameters: { type: object, properties: { role: { type: string, description: The role of the learner (i.e. developer, data scientist, student, etc.) }, product: { type: string, description: The product that the lesson is covering (i.e. Azure, Power BI, etc.) }, level: { type: string, description: The level of experience the learner has prior to taking the course (i.e. beginner, intermediate, advanced) } }, required: [role] } } ]逐个字段解释name期望被调用的函数名称必须与稍后在 Python/JS 中实现的可调用函数名一一对应description函数行为说明。这里越具体、越清晰LLM 选择正确函数、填对参数的概率越高parameters约束模型输出结构的 JSON Schema 片段包含type整体对象的类型一般为objectproperties模型将被要求产出的各字段每个属性又由name属性键名如product、type数据类型如string与description该属性的语义说明构成required可选字段列出调用函数所必需的属性。上例中只有role是必填的。第 3 步发起带工具的调用声明函数后需要把它传入 API 请求Chat Completions API 用functionsfunctionsResponses API 用toolsfunctions。同时把选择权交给模型——设置tool_choiceauto对应旧版参数function_callauto意味着由 LLM 依据用户消息自行决定调用哪个函数而不是由我们硬编码指定response client.responses.create( modeldeployment, inputmessages, toolsfunctions, tool_choiceauto, storeFalse, ) print(response.output)此时返回结果中会出现一个function_call条目在 Responses API 的response.output数组内例如{ type: function_call, name: search_courses, call_id: call_abc123, arguments: { \role\: \student\, \product\: \Azure\, \level\: \beginner\ } }注意看模型并没有执行任何真实动作它只是基于messages的内容抽取出了student、Azure、beginner作为arguments仍是 JSON 字符串提供给search_courses。这种“从提示词中提取信息 交给结构化函数签名”的做法既能复用逻辑又能给 LLM 强约束。值得一提的是仓库 js-githubmodels/app.js 中的 JavaScript 示例同样演示了这一思想模型以finish_reason tool_calls表明要调用工具并把tool_calls[0].function.name与arguments交回应用侧解析。五、把函数调用集成进真实应用拿到结构化的模型响应后下一步是在应用内跑通“解析意图 → 执行真实函数 → 回填结果 → 生成自然语言答复”的完整闭环。第 1 步从响应中筛出函数调用条目Responses API 会把函数调用作为output数组中的元素返回可用列表推导按item.type function_call过滤tool_calls [item for item in response.output if item.type function_call]第 2 步实现与声明同名的真实 Python 函数这里定义一个真正会去调用Microsoft Learn Catalog API的函数search_courses(role, product, level)请求课程列表并把前 5 个模块的标题与链接整理成列表返回import requests def search_courses(role, product, level): url https://learn.microsoft.com/api/catalog/ params { role: role, product: product, level: level } response requests.get(url, paramsparams) modules response.json()[modules] results [] for module in modules[:5]: title module[title] url module[url] results.append({title: title, url: url}) return str(results)关键点在于函数名必须与前面functions声明中的name完全一致且这里执行的是真实的外部 HTTP 请求。学习路径上更贴近实战的版本可参考 typescript/function-app/src/main.ts它用findWeather工具封装了对 Bing Maps API 的真实天气查询。第 3 步建立“函数名 → 可调用对象”的映射并执行检查响应中是否存在function_call条目若存在则通过available_functions字典把模型请求的函数名解析成真实函数用json.loads解析参数后以关键字参数方式调用if tool_calls: for tool_call in tool_calls: function_name tool_call.name available_functions { search_courses: search_courses, } function_to_call available_functions[function_name] function_args json.loads(tool_call.arguments) function_response function_to_call(**function_args)课程正文强调了执行映射最关键的三行function_to_call available_functions[function_name] function_args json.loads(tool_call.arguments) function_response function_to_call(**function_args)随后需要把模型产出的function_call条目与函数执行结果按顺序回填到messages供下一轮请求使用# 追加模型的 function_call 条目必须在函数输出之前 messages.extend(response.output) # 追加函数执行结果 messages.append({ type: function_call_output, call_id: tool_call.call_id, output: function_response, })仓库中的 JS 与 TS 实现还展示了生产级注意事项调用前校验函数名是否在白名单映射中防止注入、用 try/catch 包裹JSON.parsejs-githubmodels/app.js对外部 API 统一URLSearchParams编码参数、设置超时并避免在日志中泄漏敏感数据typescript/function-app/src/main.ts。实际运行中模型推荐的函数调用与search_courses真实返回结果示例如下Recommended Function call: search_courses Arguments: { role: student, product: Azure, level: beginner } Output of function call: [{title: Describe concepts of cryptography, url: https://learn.microsoft.com/training/modules/describe-concepts-of-cryptography/}, ...] class str第 4 步把结果交回 LLM获得自然语言答复最后把更新过的messages再次提交给模型建议配合temperature0以获得更确定的结果。此时模型已经“看到”了函数的真实输出会据此生成用户可读的自然语言回答而不再是 JSON 化的 API 响应second_response client.responses.create( inputmessages, modeldeployment, toolsfunctions, tool_choiceauto, temperature0, storeFalse, ) print(second_response.output_text)输出示例I found some good courses for beginner students to learn Azure: 1. Describe concepts of cryptography 2. Introduction to audio classification with TensorFlow 3. Design a Performant Data Model in Azure SQL Database with Azure Data Studio 4. Getting started with the Microsoft Cloud Adoption Framework for Azure 5. Set up the Rust development environment You can click on the links to access the courses.至此一个“自然语言提问 → 结构化函数调用 → 真实外部数据 → 自然语言答复”的完整链路已经打通。六、面向不同 API 体系与语言的实践对照Python / Responses API当前主路径仓库中 aoai-assignment.ipynb 使用client.responses.create、tools、tool_choiceauto、storeFalse函数调用条目通过item.type function_call识别函数结果以function_call_output含call_id回填——这也是本课程对应的希腊语翻译版本所采用的实现。OpenAI非 Azure客户端同一目录下的 oai-assignment.ipynb 走的是OpenAI官方的 Responses API结构与上文一致仅客户端初始化与端点配置不同。JavaScriptAzure AI Inference / GitHub Modelsapp.js 用azure-rest/ai-inference客户端以tools: [{type: function, function: {...}}]声明工具通过finish_reason tool_calls判断模型意图再以role: tool消息回填结果。TypeScriptResponses APImain.ts 使用扁平化的工具声明{ type: function, name, description, parameters }从result.output中按item.type function_call取出调用意图后执行真实 API。七、练习与延伸课程在末尾布置了三个进阶挑战用于把函数调用能力推向更完整的生产形态为search_courses增加更多参数帮助学习者检索到更精准的课程可参考 Microsoft Learn Catalog API 的开发者参考文档确认可用参数与数据来源再创建一个新的函数调用让模型提取学习者更多维度的信息例如其母语native language补充错误处理当函数调用或外部 API 没有返回合适课程时如何优雅降级、给出提示而非直接报错。完成本课后可继续学习下一课 12-designing-ux-for-ai-applications/README.md了解如何为这类 AI 应用设计友好的用户体验。相关的函数调用可视化素材见本课图片目录 11-integrating-with-function-calling/images/。免责声明本课程文档由机器翻译协作生成可能存在不准确之处英文原文 11-integrating-with-function-calling/README.md 为准。【免费下载链接】generative-ai-for-beginners21 Lessons, Get Started Building with Generative AI项目地址: https://gitcode.com/GitHub_Trending/ge/generative-ai-for-beginners创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门