Skip to content

Commit

Permalink
[usability] add qwen2.5 (qwq) template
Browse files Browse the repository at this point in the history
  • Loading branch information
YizhenJia committed Dec 19, 2024
1 parent 058eecd commit 62db1a9
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 1 deletion.
90 changes: 90 additions & 0 deletions docs/source/examples/supported_conversation_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
- [Mixtral 8x7B](#mixtral-8x7b)
- [Phi-3](#phi-3)
- [Qwen-2](#qwen-2)
- [Qwen-2.5](#qwen-25)
- [Yi](#yi)
- [Yi-1.5](#yi-15)
- [Zephyr](#zephyr)
Expand Down Expand Up @@ -405,6 +406,95 @@ The conversation template for Mixtral 8x7B is slightly different from the templa
```


## Qwen-2.5

(Also QwQ)

**With a system message**
```
<|im_start|>system\n{{system_message}}<|im_end|>\n<|im_start|>user\n{{user_message_0}}<|im_end|>\n
```

**Without a system message**
```
<|im_start|>user\n{{user_message_0}}<|im_end|>\n
```

**A complete conversation**
```
<|im_start|>system\n{{system_message}}<|im_end|>\n<|im_start|>user\n{{user_message_0}}<|im_end|>\n<|im_start|>assistant\n{{assistant_reply_0}}<|im_end|>\n
```

**Multiple rounds**
```
<|im_start|>system\n{{system_message}}<|im_end|>\n<|im_start|>user\n{{user_message_0}}<|im_end|>\n<|im_start|>assistant\n{{assistant_reply_0}}<|im_end|>\n<|im_start|>user\n{{user_message_1}}<|im_end|>\n<|im_start|>assistant\n{{assistant_reply_1}}<|im_end|>\n
```

**jinja template**
[[Reference]()]
```
{%- if tools %}
{{- '<|im_start|>system\\n' }}
{%- if messages[0]['role'] == 'system' %}
{{- messages[0]['content'] }}
{%- else %}
{{- 'You are a helpful and harmless assistant. You are Qwen developed by Alibaba. You should think step-by-step.' }}
{%- endif %}
{{- \"\\n\\n# Tools\\n\\nYou may call one or more functions to assist with the user query.\\n\\nYou are provided with function signatures within <tools></tools> XML tags:\\n<tools>\" }}
{%- for tool in tools %}
{{- \"\\n\" }}
{{- tool | tojson }}
{%- endfor %}
{{- \"\\n</tools>\\n\\nFor each function call, return a json object with function name and arguments within <tool_call></tool_call> XML tags:\\n<tool_call>\\n{\\\"name\\\": <function-name>, \\\"arguments\\\": <args-json-object>}\\n</tool_call><|im_end|>\\n\" }}
{%- else %}
{%- if messages[0]['role'] == 'system' %}
{{- '<|im_start|>system\\n' + messages[0]['content'] + '<|im_end|>\\n' }}
{%- else %}
{{- '<|im_start|>system\\nYou are a helpful and harmless assistant. You are Qwen developed by Alibaba. You should think step-by-step.<|im_end|>\\n' }}
{%- endif %}
{%- endif %}
{%- for message in messages %}
{%- if (message.role == \"user\") or (message.role == \"system\" and not loop.first) or (message.role == \"assistant\" and not message.tool_calls) %}
{{- '<|im_start|>' + message.role + '\\n' + message.content + '<|im_end|>' + '\\n' }}
{%- elif message.role == \"assistant\" %}
{{- '<|im_start|>' + message.role }}
{%- if message.content %}
{{- '\\n' + message.content }}
{%- endif %}
{%- for tool_call in message.tool_calls %}
{%- if tool_call.function is defined %}
{%- set tool_call = tool_call.function %}
{%- endif %}
{{- '\\n<tool_call>\\n{\"name\": \"' }}
{{- tool_call.name }}
{{- '\", \"arguments\": ' }}
{{- tool_call.arguments | tojson }}
{{- '}\\n</tool_call>' }}
{%- endfor %}
{{- '<|im_end|>\\n' }}
{%- elif message.role == \"tool\" %}
{%- if (loop.index0 == 0) or (messages[loop.index0 - 1].role != \"tool\") %}
{{- '<|im_start|>user' }}
{%- endif %}
{{- '\\n<tool_response>\\n' }}
{{- message.content }}
{{- '\\n</tool_response>' }}
{%- if loop.last or (messages[loop.index0 + 1].role != \"tool\") %}
{{- '<|im_end|>\\n' }}
{%- endif %}
{%- endif %}
{%- endfor %}
{%- if add_generation_prompt %}
{{- '<|im_start|>assistant\\n' }}
{%- endif %}
```

**Filled Example**
```
<|im_start|>system\nYou are a chatbot developed by LMFlow team.<|im_end|>\n<|im_start|>user\nWho are you?<|im_end|>\n<|im_start|>assistant\nI am a chatbot developed by LMFlow team.<|im_end|>\n<|im_start|>user\nHow old are you?<|im_end|>\n<|im_start|>assistant\nI don't age like humans do. I exist as a piece of software, so I don't have a concept of age in the traditional sense.<|im_end|>\n
```


## Yi
**With a system message**
```
Expand Down
3 changes: 2 additions & 1 deletion src/lmflow/utils/conversation_template/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from .internlm import INTERNLM2_TEMPLATE
from .llama import LLAMA2_TEMPLATE, LLAMA3_TEMPLATE, LLAMA3_TEMPLATE_FOR_TOOL
from .phi import PHI3_TEMPLATE
from .qwen import QWEN2_TEMPLATE, QWEN2_TEMPLATE_FOR_TOOL
from .qwen import QWEN2_TEMPLATE, QWEN2_TEMPLATE_FOR_TOOL, QWEN2_5_TEMPLATE
from .yi import YI1_5_TEMPLATE
from .zephyr import ZEPHYR_TEMPLATE

Expand All @@ -31,6 +31,7 @@
'phi3': PHI3_TEMPLATE,
'qwen2': QWEN2_TEMPLATE,
'qwen2_for_tool': QWEN2_TEMPLATE_FOR_TOOL,
'qwen2_5': QWEN2_5_TEMPLATE,
'yi': CHATML_TEMPLATE,
'yi1_5': YI1_5_TEMPLATE,
'zephyr': ZEPHYR_TEMPLATE
Expand Down
52 changes: 52 additions & 0 deletions src/lmflow/utils/conversation_template/qwen.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
#!/usr/bin/env python
# coding=utf-8
# Copyright 2024 Statistics and Machine Learning Research Group. All rights reserved.
from typing import Dict, Set, Sequence, Literal, Union, List, Optional, Tuple

from transformers import PreTrainedTokenizer

from .base import StringFormatter, TemplateComponent, ConversationTemplate, ConversationTemplateForTool


Expand All @@ -24,6 +28,7 @@
separator=TemplateComponent(type='string', content='\n')
)


QWEN2_TEMPLATE_FOR_TOOL = ConversationTemplateForTool(
template_name='qwen2_for_tool',
user_formatter=StringFormatter(
Expand Down Expand Up @@ -52,4 +57,51 @@
]
),
separator=TemplateComponent(type='string', content='\n')
)


class Qwen2_5ConversationTemplate(ConversationTemplateForTool):
def _handle_tools(self, tools: Optional[List[str]]) -> str:
prompt1 = "\n\n# Tools\n\nYou may call one or more functions to assist with the user query.\n\nYou are provided with function signatures within <tools></tools> XML tags:\n<tools>"
prompt2 = '\n</tools>\n\nFor each function call, return a json object with function name and arguments within <tool_call></tool_call> XML tags:\n<tool_call>\n{"name": <function-name>, "arguments": <args-json-object>}\n</tool_call>'
tools_out = ''

if tools is not None:
tools_out = prompt1
for tool in tools:
tools_out += "\n" + tool
tools_out += prompt2

return tools_out


QWEN2_5_TEMPLATE = Qwen2_5ConversationTemplate(
template_name='qwen2_5',
user_formatter=StringFormatter(
template=[
TemplateComponent(type='string', content='<|im_start|>user\n{{content}}<|im_end|>\n')
]
),
function_formatter=StringFormatter(
template=[
TemplateComponent(type='string', content='<|im_start|>assistant\n{{content}}<|im_end|>\n')
]
),
observation_formatter=StringFormatter(
template=[
TemplateComponent(type='string', content='<|im_start|>tool\n{{content}}<|im_end|>\n')
]
),
assistant_formatter=StringFormatter(
template=[
TemplateComponent(type='string', content='<|im_start|>assistant\n{{content}}<|im_end|>\n')
]
),
system_formatter=StringFormatter(
template=[
TemplateComponent(type='string', content='<|im_start|>system\n{{content}}<|im_end|>\n')
]
),
separator=TemplateComponent(type='string', content='\n'),
system_default='You are a helpful and harmless assistant. You are Qwen developed by Alibaba. You should think step-by-step.'
)

0 comments on commit 62db1a9

Please sign in to comment.