{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Openai Function Call \n", "https://platform.openai.com/docs/guides/function-calling" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "User>\t How's the weather in Hangzhou?\n", "[ChatCompletionMessageToolCall(id='call_zvxBS1zoCa6X9fJzE48BYo2z', function=Function(arguments='{\"location\":\"Hangzhou, China\"}', name='get_weather', parameters=None), type='function')]\n", "https://api.weatherapi.com/v1/current.json?key=b7e69154e60b427586983619250502&q=Hangzhou, China\n", "Tool call>\t Temperature: 13.0°C, Condition: Partly cloudy\n", "Model>\t The current weather in Hangzhou, China is partly cloudy with a temperature of 13.0°C.\n" ] } ], "source": [ "from openai import OpenAI\n", "import json\n", "import requests\n", "\n", "# 定义获取天气的工具\n", "def get_weather(location: str):\n", " \"\"\"调用天气 API 获取指定地点的天气信息\"\"\"\n", " url = f\"https://api.weatherapi.com/v1/current.json?key=b7e69154e60b427586983619250502&q={location}\"\n", " print(url)\n", " response = requests.get(url)\n", " if response.status_code == 200:\n", " data = response.json()\n", " return f\"Temperature: {data['current']['temp_c']}°C, Condition: {data['current']['condition']['text']}\"\n", " return \"Weather data not found\"\n", "\n", "def send_messages(messages):\n", " response = client.chat.completions.create(\n", " model=\"gpt-4o\",\n", " messages=messages,\n", " tools=tools, # 指定可调用的函数\n", " )\n", " return response.choices[0].message\n", "\n", "client = OpenAI(\n", " api_key=\"sk-lXFW7Bl1ruw2qmHu287e979847354601A07fE2D85a567bD7\", # pass litellm proxy key, if you're using virtual keys\n", " base_url=\"https://yunwu.ai/v1/\" # litellm-proxy-base url\n", ")\n", "\n", "tools = [{\n", " \"type\": \"function\",\n", " \"function\": {\n", " \"name\": \"get_weather\",\n", " \"description\": \"Get current temperature for a given location.\",\n", " \"parameters\": {\n", " \"type\": \"object\",\n", " \"properties\": {\n", " \"location\": {\n", " \"type\": \"string\",\n", " \"description\": \"City and country e.g. Bogotá, Colombia\"\n", " }\n", " },\n", " \"required\": [\n", " \"location\"\n", " ],\n", " \"additionalProperties\": False\n", " },\n", " \"strict\": True\n", " }\n", "}]\n", "# step1\n", "messages = [{\"role\": \"user\", \"content\": \"How's the weather in Hangzhou?\"}]\n", "message = send_messages(messages)\n", "print(f\"User>\\t {messages[0]['content']}\")\n", "print(message.tool_calls)\n", "\n", "# step2\n", "tool_call = message.tool_calls[0]\n", "\n", "#step3 tool call chioce to local function call\n", "args = json.loads(tool_call.function.arguments)\n", "result = get_weather(args[\"location\"])\n", "print(\"Tool call>\\t\", result)\n", "\n", "# step4\n", "messages.append(message) # append model's function call message\n", "messages.append({ # append result message\n", " \"role\": \"tool\",\n", " \"tool_call_id\": tool_call.id,\n", " \"content\": result\n", "})\n", "\n", "message = send_messages(messages)\n", "\n", "# step5\n", "print(\"Model>\\t\", message.content)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Qwen Tool Use Example" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "\n", "------------------------------------------------------------\n", "\n", "第1轮大模型输出信息:{'id': 'chatcmpl-91008e14-9254-98b9-8b14-da6632f6c711', 'choices': [{'finish_reason': 'tool_calls', 'index': 0, 'logprobs': None, 'message': {'content': '', 'refusal': None, 'role': 'assistant', 'audio': None, 'function_call': None, 'tool_calls': [{'id': 'call_5ae24ff6a07e4a1093fff6', 'function': {'arguments': '{}', 'name': 'get_current_time'}, 'type': 'function', 'index': 0}]}}], 'created': 1738762202, 'model': 'qwen-max-2025-01-25', 'object': 'chat.completion', 'service_tier': None, 'system_fingerprint': None, 'usage': {'completion_tokens': 13, 'prompt_tokens': 219, 'total_tokens': 232, 'completion_tokens_details': None, 'prompt_tokens_details': None}}\n", "\n", "工具输出信息:当前时间:2025-02-05 21:29:58。\n", "\n", "------------------------------------------------------------\n", "第2轮大模型输出信息:{'content': '现在的时间是2025年2月5日,晚上9点29分58秒。', 'refusal': None, 'role': 'assistant', 'audio': None, 'function_call': None, 'tool_calls': None}\n", "\n", "最终答案:现在的时间是2025年2月5日,晚上9点29分58秒。\n" ] } ], "source": [ "from openai import OpenAI\n", "from datetime import datetime\n", "import json\n", "import os\n", "\n", "client = OpenAI(\n", " # 若没有配置环境变量,请用百炼API Key将下行替换为:api_key=\"sk-xxx\",\n", " api_key=\"sk-487d366becc14df0a58ff4d4559fabf4\",\n", " base_url=\"https://dashscope.aliyuncs.com/compatible-mode/v1\", # 填写DashScope SDK的base_url\n", ")\n", "\n", "# 定义工具列表,模型在选择使用哪个工具时会参考工具的name和description\n", "tools = [\n", " # 工具1 获取当前时刻的时间\n", " {\n", " \"type\": \"function\",\n", " \"function\": {\n", " \"name\": \"get_current_time\",\n", " \"description\": \"当你想知道现在的时间时非常有用。\",\n", " # 因为获取当前时间无需输入参数,因此parameters为空字典\n", " \"parameters\": {}\n", " }\n", " }, \n", " # 工具2 获取指定城市的天气\n", " {\n", " \"type\": \"function\",\n", " \"function\": {\n", " \"name\": \"get_current_weather\",\n", " \"description\": \"当你想查询指定城市的天气时非常有用。\",\n", " \"parameters\": { \n", " \"type\": \"object\",\n", " \"properties\": {\n", " # 查询天气时需要提供位置,因此参数设置为location\n", " \"location\": {\n", " \"type\": \"string\",\n", " \"description\": \"城市或县区,比如北京市、杭州市、余杭区等。\"\n", " }\n", " }\n", " },\n", " \"required\": [\n", " \"location\"\n", " ]\n", " }\n", " }\n", "]\n", "\n", "# 模拟天气查询工具。返回结果示例:“北京今天是雨天。”\n", "def get_current_weather(location):\n", " return f\"{location}今天是雨天。 \"\n", "\n", "# 查询当前时间的工具。返回结果示例:“当前时间:2024-04-15 17:15:18。“\n", "def get_current_time():\n", " # 获取当前日期和时间\n", " current_datetime = datetime.now()\n", " # 格式化当前日期和时间\n", " formatted_time = current_datetime.strftime('%Y-%m-%d %H:%M:%S')\n", " # 返回格式化后的当前时间\n", " return f\"当前时间:{formatted_time}。\"\n", "\n", "# 封装模型响应函数\n", "def get_response(messages):\n", " completion = client.chat.completions.create(\n", " model=\"qwen-max-2025-01-25\",\n", " messages=messages,\n", " tools=tools\n", " )\n", " return completion.model_dump()\n", "\n", "def call_with_messages():\n", " print('\\n')\n", " messages = [\n", " {\n", " \"content\": input('现在几点了?'), # 提问示例:\"现在几点了?\" \"一个小时后几点\" \"北京天气如何?\"\n", " \"role\": \"user\"\n", " }\n", " ]\n", " print(\"-\"*60)\n", " # 模型的第一轮调用\n", " i = 1\n", " first_response = get_response(messages)\n", " assistant_output = first_response['choices'][0]['message']\n", " print(f\"\\n第{i}轮大模型输出信息:{first_response}\\n\")\n", " if assistant_output['content'] is None:\n", " assistant_output['content'] = \"\"\n", " messages.append(assistant_output)\n", " # 如果不需要调用工具,则直接返回最终答案\n", " if assistant_output['tool_calls'] == None: # 如果模型判断无需调用工具,则将assistant的回复直接打印出来,无需进行模型的第二轮调用\n", " print(f\"无需调用工具,我可以直接回复:{assistant_output['content']}\")\n", " return\n", " # 如果需要调用工具,则进行模型的多轮调用,直到模型判断无需调用工具\n", " while assistant_output['tool_calls'] != None:\n", " # 如果判断需要调用查询天气工具,则运行查询天气工具\n", " if assistant_output['tool_calls'][0]['function']['name'] == 'get_current_weather':\n", " tool_info = {\"name\": \"get_current_weather\", \"role\":\"tool\"}\n", " # 提取位置参数信息\n", " location = json.loads(assistant_output['tool_calls'][0]['function']['arguments'])['location']\n", " tool_info['content'] = get_current_weather(location)\n", " # 如果判断需要调用查询时间工具,则运行查询时间工具\n", " elif assistant_output['tool_calls'][0]['function']['name'] == 'get_current_time':\n", " tool_info = {\"name\": \"get_current_time\", \"role\":\"tool\"}\n", " tool_info['content'] = get_current_time()\n", " print(f\"工具输出信息:{tool_info['content']}\\n\")\n", " print(\"-\"*60)\n", " messages.append(tool_info)\n", " assistant_output = get_response(messages)['choices'][0]['message']\n", " if assistant_output['content'] is None:\n", " assistant_output['content'] = \"\"\n", " messages.append(assistant_output)\n", " i += 1\n", " print(f\"第{i}轮大模型输出信息:{assistant_output}\\n\")\n", " print(f\"最终答案:{assistant_output['content']}\")\n", "\n", "call_with_messages()" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.11" } }, "nbformat": 4, "nbformat_minor": 2 }