Qwen2.5のFunction-Calling

1,554 阅读4分钟

Function-Calling

基于Qwen2.5(Vllm部署)

  • vllm启动命令
CUDA_VISIBLE_DEVICES=7 nohup vllm serve /home/addr/ocr/xyz/models/Qwen2.5-7B-Instruct --port 7878 --served-model-name qw257i --enable-auto-tool-choice --tool-call-parser hermes >/home/addr/ocr/xyz/models/logs/qw257i.log 2>&1 &

需要添加**--enable-auto-tool-choice --tool-call-parser**启动函数调用功能

  • 准备函数
import json

def get_current_temperature(location: str, unit: str = "celsius"):
    return {
        "temperature": 26.1,
        "location": location,
        "unit": unit,
    }


def get_temperature_date(location: str, date: str, unit: str = "celsius"):
    return {
        "temperature": 25.9,
        "location": location,
        "date": date,
        "unit": unit,
    }


def get_function_by_name(name):
    if name == "get_current_temperature":
        return get_current_temperature
    if name == "get_temperature_date":
        return get_temperature_date
#工具应使用JSON Schema进行描述,消息应包含尽可能多的有效信息。
TOOLS = [
    {
        "type": "function",
        "function": {
            "name": "get_current_temperature",
            "description": "Get current temperature at a location.",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": 'The location to get the temperature for, in the format "City, State, Country".',
                    },
                    "unit": {
                        "type": "string",
                        "enum": ["celsius", "fahrenheit"],
                        "description": 'The unit to return the temperature in. Defaults to "celsius".',
                    },
                },
                "required": ["location"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_temperature_date",
            "description": "Get temperature at a location and date.",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": 'The location to get the temperature for, in the format "City, State, Country".',
                    },
                    "date": {
                        "type": "string",
                        "description": 'The date to get the temperature for, in the format "Year-Month-Day".',
                    },
                    "unit": {
                        "type": "string",
                        "enum": ["celsius", "fahrenheit"],
                        "description": 'The unit to return the temperature in. Defaults to "celsius".',
                    },
                },
                "required": ["location", "date"],
            },
        },
    },
]
MESSAGES = [
    {"role": "system", "content": "You are Qwen, created by Alibaba Cloud. You are a helpful assistant.\n\nCurrent Date: 2024-09-30"},
    {"role": "user",  "content": "What's the temperature in San Francisco now? How about tomorrow?"},
]

tools = TOOLS
messages = MESSAGES[:]

其中TOOLS包括两个工具,每个工具是具有两个字段的JSON Object:

  • type:string,指定工具类型(仅对function有效)
  • function:object,详细说明了如何使用函数

​ 每个function,是一个具有三个字段的JSON Object:

	1. name:函数的名称
	2. description:函数的用途
	3. parameters:[JSON Schema](https://json-schema.org/learn/getting-started-step-by-step),函数的参数
   - type:参数的类型
   - properties:对象应该具有的属性
   - required:必需的属性
  • 定义llm

    load_dotenv(find_dotenv("../.envs"))
    
    llm_base_url = os.getenv("llm_base_url")
    llm_api_key = os.getenv("llm_api_key")
    llm_api_model = os.getenv("llm_api_model")
    
    
    llm = OpenAI(
        api_key=llm_api_key,
        base_url=llm_base_url,
    )
    
  • 工具调用和结果

response = llm.chat.completions.create(
    model=llm_api_model,
    messages=messages,
    tools=tools,
    temperature=0.7,
    top_p=0.8,
    max_tokens=512,
    extra_body={
        "repetition_penalty": 1.05,
    },
)
print(response.choices[0].message.model_dump(),"123")

#输出结果
ChatCompletion(
    id='chat-d1f25c4a209a48c9a04bf3a9783bfb31', 
    choices=[Choice(
        finish_reason='tool_calls', index=0, logprobs=None, 
        message=ChatCompletionMessage(
            content=None, role='assistant', function_call=None, 
            tool_calls=[
                ChatCompletionMessageToolCall(
                    id='chatcmpl-tool-553147485abd472f9bde21d1d4cf6734', 
                	function=Function(
                    	arguments='{"location": "San Francisco, CA, USA"}', 
                    	name='get_current_temperature'), 
                		type='function'), 
               	ChatCompletionMessageToolCall(
                    id='chatcmpl-tool-773d3f5ea9ae4652bae370f1365a5c44', 
                    function=Function(
                        arguments='{"location": "San Francisco, CA, USA", "date": "2024-10-01"}',
                        name='get_temperature_date'), 
                    type='function')]
        ), 
        stop_reason=None)], 
    created=1728453800,
    model='qw257i', 
    object='chat.completion', 
    service_tier=None,
    system_fingerprint=None, 
    usage=CompletionUsage(
        completion_tokens=67, 
        prompt_tokens=412,                                            
        total_tokens=479), 
    prompt_logprobs=None) 123

通过以上,知道了调用函数的arguments和name

转换成字典,并添加到messages中

messages.append(response.choices[0].message.model_dump())
[{
    'role': 'system', 
    'content': 'You are Qwen, created by Alibaba Cloud. You are a helpful assistant.\n\nCurrent Date: 2024-09-30'},
    {'role': 'user', 
     'content': "What's the temperature in San Francisco now? How about tomorrow?"}, 
    {'content': None, 'role': 'assistant', 'function_call': None, 
     'tool_calls': [
         {'id': 'chatcmpl-tool-8681f280b0284fd180e5cf1e5d7af995', 
          'function': {
              'arguments': '{"location": "San Francisco, CA, USA"}',
              'name': 'get_current_temperature'}, 
          'type': 'function'}, 
         {'id': 'chatcmpl-tool-f8068c6567b64efcb0974cdfcf9c8a31',
          'function': {
              'arguments': '{"location": "San Francisco, CA, USA", "date": "2024-10-01"}', 
              'name': 'get_temperature_date'}, 'type': 'function'}]
    }
]
#调用函数
if tool_calls := messages[-1].get("tool_calls", None):
    for tool_call in tool_calls:
        call_id: str = tool_call["id"]
        if fn_call := tool_call.get("function"):
            fn_name: str = fn_call["name"]
            fn_args: dict = json.loads(fn_call["arguments"])
        	#获取到的参数和名字进行函数调用(关键代码)
            fn_res: str = json.dumps(get_function_by_name(fn_name)(**fn_args))

            messages.append({
                "role": "tool",
                "content": fn_res,
                "tool_call_id": call_id,
            })
[{
    'role': 'system', 
    'content': 'You are Qwen, created by Alibaba Cloud. You are a helpful assistant.\n\nCurrent Date: 2024-09-30'}, 
    {'role': 'user', 
     'content': "What's the temperature in San Francisco now? How about tomorrow?"}, 
    {'content': None, 'role': 'assistant', 'function_call': None, 
     'tool_calls': [{
         'id': 'chatcmpl-tool-3edce328899a44c2b5c1961f5086fc83', 
         'function': {
             'arguments': '{"location": "San Francisco, CA, USA"}', 
             'name': 'get_current_temperature'}, 
         'type': 'function'}, 
         {'id': 'chatcmpl-tool-363519d0e69a485192a0d9baeae38626', 
          'function': {
              'arguments': '{"location": "San Francisco, CA, USA", "date": "2024-10-01"}', 
              'name': 'get_temperature_date'}, 
          'type': 'function'}]},
    {'role': 'tool', 
     'content': '{"temperature": 26.1, "location": "San Francisco, CA, USA", "unit": "celsius"}', 
     'tool_call_id': 'chatcmpl-tool-3edce328899a44c2b5c1961f5086fc83'}, 
    {'role': 'tool',
     'content': '{"temperature": 25.9, "location": "San Francisco, CA, USA", "date": "2024-10-01", "unit": "celsius"}', 
     'tool_call_id': 'chatcmpl-tool-363519d0e69a485192a0d9baeae38626'}]

可以看到,函数返回已经添加到message中

  • 最后调用llm,给模型提供工具结果并获得回复,相当于整理message
response = llm.chat.completions.create(
    model=llm_api_model,
    messages=messages,
    tools=tools,
    temperature=0.7,
    top_p=0.8,
    max_tokens=512,
    extra_body={
        "repetition_penalty": 1.05,
    },
)
print(response.choices[0].message.content)
The current temperature in San Francisco is approximately 26.1°C. Tomorrow, on October 1st, 2024, the temperature is expected to be around 25.9°C.