大模型意图识别

一、意图识别传统方法

过去为了识别用户意图,可以使用训练的方式,或者使用prompt

1.1 微调大模型识别指令

1.2 通过prompt指导大模型识别指令

可以使用如下prompt:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
### 背景
有两个API接口:
1. 下单API:支持传入商家名称、商品名称。
2. 搜索API:支持传入地点与距离进行搜索,API会返回外卖商家和商品列表。

### 要求
根据输入的文本,需要决定是否调用API,调用哪个API并生成对应的查询结构体。
回答的时候给出: 1.下一步动作(action) 2.是否调用和调用哪个API 3.回复语句 4.查询结构体。

### 示例
问题:我在新街口,想吃20元左右的黄焖鸡。
答案:{ action: 'call', api: 2, params: ['新街口’, 20, '黄焖鸡']}
问题: 好的,我想吃杨铭宇黄焖鸡
答案:{action: 'call', api: 1, params:['', '', '杨铭宇黄焖鸡']}

### 问题
问题: 我点一份麻辣烫

使用qwen-14b-chat模型,有如下回答:

1
{ action: 'call', api: 1, params:['', '', '麻辣烫']} 回复语句: 好的,我已经帮您下单了一份麻辣烫,请注意查收。

使用hunyuan-13b模型,有如下回答:

1
{ action: 'call', api: 1, params:['', '', '麻辣烫'] }

使用gpt-4o模型,有如下回答

1
2
3
4
5
6
答案:{ action: 'call', api: 1, params: ['', '麻辣烫']}

下一步动作(action): call
是否调用和调用哪个API: 调用下单API
回复语句: 正在为您下单麻辣烫。
查询结构体: ['', '麻辣烫']

使用GPT-4模型,有如下回答:

1
答案:{action: 'call', api: 1, params:['', '', '麻辣烫']}

也可以按如下方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
现在有函数的描述:
{
        "type": "function",
        "function": {
            "name": "get_flight_number",
            "description": "根据始发地、目的地和日期,查询对应日期的航班号",
            "parameters":
                "type": "object",
                "properties": {
                    "departure": {
                        "description": "出发地",
                        "type": "string"
                    },
                    "destination": {
                        "description": "目的地",
                        "type": "string"
                    },
                    "date": {
                        "description": "日期",
                        "type": "string",
                    }
                },
                "required": [ "departure", "destination", "date" ]
            },
        }
    },



依据上述两个函数的描述,我想查一下从北京到天津 20240322 的航班,请问该选择哪个函数,并以 json 的格式返回函数对应的参数

返回如下:

1
2
3
4
5
6
7
8
9
您好!根据您的需求,您应该选择第一个函数,即 get_flight_number。以下是函数对应的参数以 JSON 格式返回:

{
"departure": "北京",
"destination": "天津",
"date": "20240322"
}

希望这个答案对您有所帮助!

二、结合langchain llm路由识别意图

在langchain中,RouterChain是根据输入动态的选择下一个链,每条链处理特定类型的输入。

RouterChain由两个组件组成:

1)路由器链本身,负责选择要调用的下一个链,主要有2种RouterChain,其中LLMRouterChain通过LLM进行路由决策,EmbeddingRouterChain 通过向量搜索的方式进行路由决策。

2)目标链列表,路由器链可以路由到的子链。

2.1 利用LLM进行路由

llm路由流程:

  1. 创建多个Prompt,利用MULTI_PROMPT_ROUTER_TEMPLATE.format()方法得到router_template。
  2. 再利用PromptTemplate得到router_prompt
  3. 利用LLMRouterChain.from_llm(llm, router_prompt)就得到router_chain。
  4. 最后使用MultiPromptChain(),得到调用chain。

具体代码可见:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
from langchain.chains.router import MultiPromptChain
from langchain.llms import OpenAI
from langchain_community.llms import Tongyi
import os
from langchain.chains import ConversationChain
from langchain.chains.llm import LLMChain
from langchain.prompts import PromptTemplate
from langchain.chains.router.llm_router import LLMRouterChain, RouterOutputParser
from langchain.chains.router.multi_prompt_prompt import MULTI_PROMPT_ROUTER_TEMPLATE


# 主要创建两个知识域的模板,一个物理学、一个数学

physics_template = """You are a very smart physics professor. \
You are great at answering questions about physics in a concise and easy to understand manner. \
When you don't know the answer to a question you admit that you don't know.

Here is a question:
{input}"""


math_template = """You are a very good mathematician. You are great at answering math questions. \
You are so good because you are able to break down hard problems into their component parts, \
answer the component parts, and then put them together to answer the broader question.

Here is a question:
{input}"""

lawyer_template = """ 你是一个法律顾问,你需要根据用户提出的问题给出专业的法律意见,如果你不知道,请说"我不知道",请不要提供超出文本范围外的内容,也不要自创内容。
用户提问:
{input}
"""

sales_template = """ 你是一个销售顾问,你需要为用户输入的商品进行介绍,你需要提供商品基本信息,以及其使用方式和保修条款。
用户输入的商品:
{input}
"""

english_teacher_template ="""你是一个英语老师,用户输入的中文词汇,你需要提供对应的英文单词,包括单词词性,对应的词组和造句。
用户输入的中文词汇:
{input}
"""

poet_template=""" 你是一个诗人,你需要根据用户输入的主题作诗。
用户输入的主题:
{input}
"""


prompt_infos = [
{
"name": "physics",
"description": "Good for answering questions about physics",
"prompt_template": physics_template,
},
{
"name": "math",
"description": "Good for answering math questions",
"prompt_template": math_template,
},

{
"name": "lawyer",
"description": "咨询法律相关问题时很专业",
"prompt_template": lawyer_template,
},
{
"name": "sales",
"description": "咨询商品信息时很专业",
"prompt_template": sales_template,
},
{
"name": "english teacher",
"description": "能够很好地解答英语问题",
"prompt_template": english_teacher_template,
},
{
"name": "poet",
"description": "作诗很专业",
"prompt_template": poet_template,
}
]

# llm = OpenAI()
llm = Tongyi(dashscope_api_key=os.environ['ALI_API_KEY'])

# 下面这段主要通过遍历得到destination_chains
destination_chains = {}
for p_info in prompt_infos:
name = p_info["name"]
prompt_template = p_info["prompt_template"]
prompt = PromptTemplate(template=prompt_template, input_variables=["input"])
chain = LLMChain(llm=llm, prompt=prompt)
destination_chains[name] = chain
# 得到一个起始chain 当Router Chain无法找到合适的下游子链时,会自动路由到的默认链,可以认为是一个兜底备选链
default_chain = ConversationChain(llm=llm, output_key="text")

#创建一个list储存对应的子链名称和描述
destinations = [f"{p['name']}: {p['description']}" for p in prompt_infos]
#把描述连接成一个str
destinations_str = "\n".join(destinations)
# 格式化完毕后,其会生成一个str,这个字符串能作为prompt template了,我们来打印以下router_template
router_template = MULTI_PROMPT_ROUTER_TEMPLATE.format(destinations=destinations_str)
print("router_template=",router_template)
router_prompt = PromptTemplate(
template=router_template,
input_variables=["input"],
output_parser=RouterOutputParser(),
)
# 得到路由链
router_chain = LLMRouterChain.from_llm(llm, router_prompt)
# 参数:路由Chain、目标chain、兜底chain
chain = MultiPromptChain(
router_chain=router_chain,
destination_chains=destination_chains,
default_chain=default_chain,
verbose=True,
)

print(chain.run("什么是黑体辐射?"))

print(chain.run("第一个大于 40 的质数是多少,且该质数的一加能被 3 整除"))

print(chain.run("帮我写一首关于春天的诗"))

输出日志如下,经测试,通义千问和openai可以

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
router_template= Given a raw text input to a language model select the model prompt best suited for the input. You will be given the names of the available prompts and a description of what the prompt is best suited for. You may also revise the original input if you think that revising it will ultimately lead to a better response from the language model.

<< FORMATTING >>
Return a markdown code snippet with a JSON object formatted to look like:
``json
{{
"destination": string \ name of the prompt to use or "DEFAULT"
"next_inputs": string \ a potentially modified version of the original input
}}
``

REMEMBER: "destination" MUST be one of the candidate prompt names specified below OR it can be "DEFAULT" if the input is not well suited for any of the candidate prompts.
REMEMBER: "next_inputs" can just be the original input if you don't think any modifications are needed.

<< CANDIDATE PROMPTS >>
physics: Good for answering questions about physics
math: Good for answering math questions
lawyer: 咨询法律相关问题时很专业
sales: 咨询商品信息时很专业
english teacher: 能够很好地解答英语问题
poet: 作诗很专业

<< INPUT >>
{input}

<< OUTPUT (must include ```json at the start of the response) >>
<< OUTPUT (must end with ```) >>

/data/tlinux_python/tmgragent/venv/lib/python3.10/site-packages/langchain_core/_api/deprecation.py:119: LangChainDeprecationWarning: The method `Chain.run` was deprecated in langchain 0.1.0 and will be removed in 0.3.0. Use invoke instead.
warn_deprecated(


> Entering new MultiPromptChain chain...
physics: {'input': '解释一下什么是黑体辐射?'}
> Finished chain.
黑体辐射是指一个理想的物体,称为黑体,所发出的电磁辐射。这种物体完全吸收所有入射的辐射,而不反射或透射任何光线,并且在热平衡状态下,它会以特定的频谱分布发射出辐射。这个频谱分布与黑体的温度有关,被称为普朗克定律。

在物理学中,黑体是一个理论概念,用于研究和理解电磁辐射与物质相互作用的基本原理。普朗克在1900年提出的量子假说成功地解释了黑体辐射的谱线,这标志着量子力学的开端。黑体辐射的研究对于理解和制定热力学、统计物理以及天文学中的许多现象都至关重要。


> Entering new MultiPromptChain chain...
math: {'input': '找出第一个大于40的质数,且这个质数加1后可以被3整除。'}
> Finished chain.
要找到第一个大于40的质数,且这个质数加1后可以被3整除,我们可以按照以下步骤来解决:

1. 从41开始(因为41是大于40的第一个质数),逐个检查每个自然数是否为质数。
2. 检查每个数n是否满足以下两个条件:
a. n 是质数:这意味着它只有1和自身两个正因数。
b. n + 1 可以被3整除:即 (n + 1) % 3 == 0。

我们从41开始进行检查:

- 41 不是3的倍数(41 + 1 = 42,42是3的倍数,但41不是质数)
- 43 是质数,但 43 + 1 = 44,44不是3的倍数
- 47 是质数,且 47 + 1 = 48,48是3的倍数

所以,第一个大于40的质数,且这个质数加1后可以被3整除的是47。


> Entering new MultiPromptChain chain...
poet: {'input': '请帮我创作一首描绘春天美景的诗'}
> Finished chain.
春风吹绿江南岸,万物复苏显生机,
桃红柳绿映日辉,花开花落知时节。
燕舞蝶飞绕花间,呢喃细语春之曲,
溪水潺潺带雪融,唤醒沉睡的泥土。

金黄油菜花如海,醉人心扉香四溢,
碧空如洗云轻飘,风筝翱翔在天际。
樱桃垂丝笑春风,梨花如雪满枝头,
鸟儿啾唧唤新朋,一曲春歌荡漾久。

田野翠绿铺新装,麦苗摇曳生希望,
山川披上嫩绿袍,生机勃发春光长。
傍晚斜阳映天边,霞光万道洒人间,
春天的画卷徐徐展,美不胜收在眼前。

春风十里柔情深,温暖如诗入心扉,
世间繁华皆可忘,唯有春色最珍贵。
让我们欢歌赞美春,感恩大地的恩赐,
在这美丽的季节里,心中充满希望与欢喜。

2.2 利用embeddings进行路由

利用embeddings,进行路由

  1. 创建names_and_descriptions 。
  2. 利用EmbeddingRouterChain.from_names_and_descriptions()得到router_chain。
  3. 最后使用MultiPromptChain(),得到调用chain。

具体代码可见

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import os
from langchain.chains.router.embedding_router import EmbeddingRouterChain
from langchain.chains.router import MultiPromptChain
from langchain.embeddings import OpenAIEmbeddings
from langchain.llms import OpenAI
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain
from langchain.vectorstores import Chroma
from langchain.chains import ConversationChain

physics_template = """You are a very smart physics professor. \
You are great at answering questions about physics in a concise and easy to understand manner. \
When you don't know the answer to a question you admit that you don't know.

Here is a question:
{input}"""


math_template = """You are a very good mathematician. You are great at answering math questions. \
You are so good because you are able to break down hard problems into their component parts, \
answer the component parts, and then put them together to answer the broader question.

Here is a question:
{input}"""

lawyer_template = """ 你是一个法律顾问,你需要根据用户提出的问题给出专业的法律意见,如果你不知道,请说"我不知道",请不要提供超出文本范围外的内容,也不要自创内容。
用户提问:
{input}
"""

sales_template = """ 你是一个销售顾问,你需要为用户输入的商品进行介绍,你需要提供商品基本信息,以及其使用方式和保修条款。
用户输入的商品:
{input}
"""

english_teacher_template ="""你是一个英语老师,用户输入的中文词汇,你需要提供对应的英文单词,包括单词词性,对应的词组和造句。
用户输入的中文词汇:
{input}
"""

poet_template=""" 你是一个诗人,你需要根据用户输入的主题作诗。
用户输入的主题:
{input}
"""

prompt_infos = [
{
"name": "physics",
"description": "Good for answering questions about physics",
"prompt_template": physics_template,
},
{
"name": "math",
"description": "Good for answering math questions",
"prompt_template": math_template,
},
{
"name": "lawyer",
"description": "咨询法律相关问题时很专业",
"prompt_template": lawyer_template,
},
{
"name": "sales",
"description": "咨询商品信息时很专业",
"prompt_template": sales_template,
},
{
"name": "english teacher",
"description": "能够很好地解答英语问题",
"prompt_template": english_teacher_template,
},
{
"name": "poet",
"description": "作诗很专业",
"prompt_template": poet_template,
}
]

llm = OpenAI(temperature=0.7,model="gpt-3.5-turbo-instruct")

# 下面这段主要通过遍历得到destination_chains
destination_chains = {}
for p_info in prompt_infos:
name = p_info["name"]
prompt_template = p_info["prompt_template"]
prompt = PromptTemplate(template=prompt_template, input_variables=["input"])
chain = LLMChain(llm=llm, prompt=prompt)
destination_chains[name] = chain
# 得到一个起始chain 当Router Chain无法找到合适的下游子链时,会自动路由到的默认链,可以认为是一个兜底备选链
default_chain = ConversationChain(llm=llm, output_key="text")


names_and_descriptions = [
("physics", ["for questions about physics"]),
("math", ["for questions about math"]),
("lawyer", ["咨询法律相关问题时很专业"]),
("poet", ["作诗很专业"]),
]
router_chain = EmbeddingRouterChain.from_names_and_descriptions(
names_and_descriptions, Chroma, OpenAIEmbeddings(), routing_keys=["input"]
)
# 路由链,通过embedding来选择需要调用destination中的哪个chain
chain = MultiPromptChain(
router_chain=router_chain,
destination_chains=destination_chains,
default_chain=default_chain,
verbose=True,
)

# 使用 EmbeddingRouterChain
print(chain.run("什么是黑体辐射?"))

print(chain.run("第一个大于 40 的质数是多少,且该质数的一加能被 3 整除"))

print(chain.run("帮我写一首关于春天的诗"))

三、意图识别新方法:Function Call

gpt中的function call可以让开发者在调用 GPT-4 和 GPT-3.5-turbo 模型时,描述函数并让模型智能地输出一个包含调用这些函数所需参数的 JSON 对象。这种功能可以更可靠地将 GPT 的能力与外部工具和 API 进行连接,从而实现以下应用:

  • 创建聊天机器人:开发者可以通过调用外部工具,如 ChatGPT 插件,回答问题,或者将查询「北京的天气如何?」转换为调用 getCurrentWeather(location: string) 的函数。
  • 将自然语言转换为 API 调用或数据库查询:例如,将查询「这个月我的前十个客户是谁?」转换为调用 get_customers_by_revenue(start_date, end_date, limit) 的内部 API 调用,或者将查询「上个月 Acme 公司下了多少订单?」转换为使用 sql_query(query)的 SQL 查询。
    从文本中提取结构化数据:开发者可以定义一个名为 extract_people_data(people) 的函数,以提取在维基百科文章中提到的所有人物。

Function call,就是通过大模型选择函数以及获取函数的参数。当前ChatGLM3和llama3都支持了function call

3.1 LLM function call训练

训练数据格式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<|system|>
Answer the following questions as best as you can. You have access to the following tools:
[
{
"name": "get_current_weather",
"description": "Get the current weather in a given location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA",
},
"unit": {"type": "string"},
},
"required": ["location"],
},
}
]
<|user|>
今天北京的天气怎么样?
<|assistant|>
好的,让我们来查看今天的天气
<|assistant|>get_current_weather
`python
tool_call(location="beijing", unit="celsius")
`
<|observation|>
{"temperature": 22}
<|assistant|>
根据查询结果,今天北京的气温为 22 摄氏度。

3.2 使用llm function

  1. 使用functions字段插入function_call函数。设置functions字段已经设置function_callauto,让大模型自己选择是否要使用functions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
full_response = ""
response = client.chat.completions.create(
model=model,
temperature=0,
messages=history,
stream=False,
functions=[
{
"name": "get_current_weather",
"description": "Get the current weather in a given location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA",
},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
},
"required": ["location"],
},
}
],
function_call="auto",
)
print('ddtest response', response)
full_response += response.choices[0].message.content

返回如下:

1
2
3
4
5
6
7
8
9
input: 你好
output: ChatCompletion(id='chatcmpl-9Wef5obmSYvBGlFIsZlTe5psrGdAG', choices=[Choice(finish_reason='stop', index=0, logprobs=None, message=ChatCompletionMessage(content='你好!有什么我可以帮忙的吗?', role='assistant', function_call=None, tool_calls=None))], created=1717569827, model='gpt-4o-2024-05-13', object='chat.completion', system_fingerprint='fp_319be4768e', usage=CompletionUsage(completion_tokens=10, prompt_tokens=73, total_tokens=83))
input: 北京天气怎么样
# gpt-4o返回
output: ChatCompletion(id='chatcmpl-9WefCIfAvcAbWMdg8qXuWLE5lAoe9', choices=[Choice(finish_reason='function_call', index=0, logprobs=None, message=ChatCompletionMessage(content=None, role='assistant', function_call=FunctionCall(arguments='{"location":"北京","unit":"celsius"}', name='get_current_weather'), tool_calls=None))], created=1717569834, model='gpt-4o-2024-05-13', object='chat.completion', system_fingerprint='fp_319be4768e', usage=CompletionUsage(completion_tokens=20, prompt_tokens=93, total_tokens=113))
# hunyuan-13b返回
output: ChatCompletion(id='818871cb-6fa6-4768-9cf4-cbb4259419c0', choices=[Choice(finish_reason=None, index=0, logprobs=None, message=ChatCompletionMessage(content='你好!很高兴见到你。关于北京天气,我无法实时提供天气信息。你可以查看一下当地的天气预报或使用手机上的天气应用来获取最新的天气信息。', role='assistant', function_call=None, tool_calls=None))], created=None, model=None, object='chat.completion', system_fingerprint=None, usage=CompletionUsage(completion_tokens=34, prompt_tokens=18, total_tokens=52), venusMarker={'spanId': 'd7f903ebe3b01935'})
# qwen返回
ChatCompletion(id='6bbe684d-e294-4311-b7c7-01c820400b81', choices=[Choice(finish_reason=None, index=0, logprobs=None, message=ChatCompletionMessage(content='北京今天天气晴朗,气温较低,建议出门携带外套。', role='assistant', function_call=None, tool_calls=None))], created=None, model=None, object='chat.completion', system_fingerprint=None, usage=CompletionUsage(completion_tokens=15, prompt_tokens=41, total_tokens=56), venusMarker={'spanId': '0f03055e1085d192'})
  1. 使用tools方式使用function_call
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
tools = [
{
"type": "function",
"function": {
"name": "get_flight_number",
"description": "根据始发地、目的地和日期,查询对应日期的航班号",
"parameters": {
"type": "object",
"properties": {
"departure": {
"description": "出发地",
"type": "string"
},
"destination": {
"description": "目的地",
"type": "string"
},
"date": {
"description": "日期",
"type": "string",
}
},
"required": [ "departure", "destination", "date" ]
},
}
},
{
"type": "function",
"function": {
"name": "get_ticket_price",
"description": "查询某航班在某日的票价",
"parameters": {
"type": "object",
"properties": {
"flight_number": {
"description": "航班号",
"type": "string"
},
"date": {
"description": "日期",
"type": "string",
}
},
"required": [ "flight_number", "date"]
},
}
},
{
"type": "function",
"function":{
"name": "get_current_weather",
"description": "Get the current weather in a given location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA",
},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
},
"required": ["location"],
},
}
}
]
with st.chat_message("assistant"):
message_placeholder = st.empty()
full_response = ""
response = client.chat.completions.create(
model=model,
temperature=0,
messages=history,
stream=False,
tools=tools,
tool_choice="auto",
)
print('ddtest response', response)
full_response += response.choices[0].message.content

返回如下:

1
2
3
4
5
6
7
8
9
input: 你好
output: ChatCompletion(id='chatcmpl-9Wef5obmSYvBGlFIsZlTe5psrGdAG', choices=[Choice(finish_reason='stop', index=0, logprobs=None, message=ChatCompletionMessage(content='你好!有什么我可以帮忙的吗?', role='assistant', function_call=None, tool_calls=None))], created=1717569827, model='gpt-4o-2024-05-13', object='chat.completion', system_fingerprint='fp_319be4768e', usage=CompletionUsage(completion_tokens=10, prompt_tokens=73, total_tokens=83))
input: 北京天气怎么样
# gpt-4o返回
output: ChatCompletion(id='chatcmpl-9WfHHaqmVIUJLAgsfploUzatzCNjz', choices=[Choice(finish_reason='tool_calls', index=0, logprobs=None, message=ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_gcgMhrCMlY1TB1yTxU7ECdwg', function=Function(arguments='{\n "location": "北京",\n "unit": "celsius"\n}', name='get_current_weather'), type='function')]))], created=1717572195, model='gpt-4o-2024-05-13', object='chat.completion', system_fingerprint='fp_5f4bad809a', usage=CompletionUsage(completion_tokens=24, prompt_tokens=222, total_tokens=246), venusMarker={'spanId': '46fc40c70f0fb8ec'})
# hunyuan-13b返回
output: ChatCompletion(id='818871cb-6fa6-4768-9cf4-cbb4259419c0', choices=[Choice(finish_reason=None, index=0, logprobs=None, message=ChatCompletionMessage(content='你好!很高兴见到你。关于北京天气,我无法实时提供天气信息。你可以查看一下当地的天气预报或使用手机上的天气应用来获取最新的天气信息。', role='assistant', function_call=None, tool_calls=None))], created=None, model=None, object='chat.completion', system_fingerprint=None, usage=CompletionUsage(completion_tokens=34, prompt_tokens=18, total_tokens=52), venusMarker={'spanId': 'd7f903ebe3b01935'})
# qwen返回
ChatCompletion(id='6bbe684d-e294-4311-b7c7-01c820400b81', choices=[Choice(finish_reason=None, index=0, logprobs=None, message=ChatCompletionMessage(content='北京今天天气晴朗,气温较低,建议出门携带外套。', role='assistant', function_call=None, tool_calls=None))], created=None, model=None, object='chat.completion', system_fingerprint=None, usage=CompletionUsage(completion_tokens=15, prompt_tokens=41, total_tokens=56), venusMarker={'spanId': '0f03055e1085d192'})

参考

  1. chatglm3 微调function call: https://blog.csdn.net/qq_35812205/article/details/135724834
  2. langchain 中文网 embeddingchain https://python.langchain.com.cn/docs/modules/chains/foundational/router