Instructions to use nlpguy/Qwen3.8-27B-Kimiko-2 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use nlpguy/Qwen3.8-27B-Kimiko-2 with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("image-text-to-text", model="nlpguy/Qwen3.8-27B-Kimiko-2") messages = [ { "role": "user", "content": [ {"type": "image", "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/p-blog/candy.JPG"}, {"type": "text", "text": "What animal is on the candy?"} ] }, ] pipe(text=messages)# pip install -U transformers accelerate # Load model directly from transformers import AutoProcessor, AutoModelForMultimodalLM processor = AutoProcessor.from_pretrained("nlpguy/Qwen3.8-27B-Kimiko-2") model = AutoModelForMultimodalLM.from_pretrained("nlpguy/Qwen3.8-27B-Kimiko-2", device_map="auto") messages = [ { "role": "user", "content": [ {"type": "image", "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/p-blog/candy.JPG"}, {"type": "text", "text": "What animal is on the candy?"} ] }, ] inputs = processor.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=256) print(processor.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use nlpguy/Qwen3.8-27B-Kimiko-2 with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "nlpguy/Qwen3.8-27B-Kimiko-2" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "nlpguy/Qwen3.8-27B-Kimiko-2", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }'Use Docker
docker model run hf.co/nlpguy/Qwen3.8-27B-Kimiko-2
- SGLang
How to use nlpguy/Qwen3.8-27B-Kimiko-2 with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "nlpguy/Qwen3.8-27B-Kimiko-2" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "nlpguy/Qwen3.8-27B-Kimiko-2", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "nlpguy/Qwen3.8-27B-Kimiko-2" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "nlpguy/Qwen3.8-27B-Kimiko-2", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }' - Docker Model Runner
How to use nlpguy/Qwen3.8-27B-Kimiko-2 with Docker Model Runner:
docker model run hf.co/nlpguy/Qwen3.8-27B-Kimiko-2
Download chat_template.jinja from nlpguy/Qwen3.8-27B-Kimiko-2: direct link, hf CLI and curl.
- Browser
- Download file 27.1 kB
-
https://huggingface.co/nlpguy/Qwen3.8-27B-Kimiko-2/resolve/174943c4b16d7d89f60275e42b3ec565c8a6b0cf/chat_template.jinja
- Command line
-
hf download hf://nlpguy/Qwen3.8-27B-Kimiko-2@174943c4b16d7d89f60275e42b3ec565c8a6b0cf/chat_template.jinja
-
curl -L -o chat_template.jinja https://huggingface.co/nlpguy/Qwen3.8-27B-Kimiko-2/resolve/174943c4b16d7d89f60275e42b3ec565c8a6b0cf/chat_template.jinja
27.1 kB
| {%- set template_version = "qwen3.8-safe-v2" %} | |
| {#- ------------------------------------------------------------------------- | |
| Whitespace contract: every tag opener in this file carries a leading minus, | |
| so it strips the whitespace and newlines that precede it. All emitted text | |
| comes from string literals, which makes the rendered prompt byte-exact and | |
| free of incidental newlines. Comment tags need the minus just as much as | |
| block tags do; a plain comment tag breaks the strip chain and leaks the | |
| surrounding indentation into the prompt. | |
| ------------------------------------------------------------------------- -#} | |
| {#- The message list has to exist before anything else can inspect it. -#} | |
| {%- if not messages %} | |
| {{- raise_exception('No messages provided.') }} | |
| {%- endif %} | |
| {#- ------------------------------------------------------------------------- | |
| Configuration | |
| ------------------------------------------------------------------------- -#} | |
| {%- set _requested_tool_format = | |
| tool_call_format if tool_call_format is defined else 'auto' | |
| %} | |
| {%- if _requested_tool_format not in ('auto', 'xml', 'json') %} | |
| {{- raise_exception( | |
| 'Unexpected tool_call_format ' ~ _requested_tool_format ~ | |
| '. Supported values are auto (default), xml, and json.' | |
| ) }} | |
| {%- endif %} | |
| {%- set add_vision_id = add_vision_id if add_vision_id is defined else false %} | |
| {%- set enable_thinking = enable_thinking if enable_thinking is defined else true %} | |
| {%- set auto_disable_thinking_with_tools = | |
| auto_disable_thinking_with_tools | |
| if auto_disable_thinking_with_tools is defined | |
| else false | |
| %} | |
| {%- if preserve_reasoning is defined | |
| and preserve_reasoning is not none | |
| and preserve_thinking is defined | |
| and preserve_thinking is not none | |
| and preserve_reasoning != preserve_thinking %} | |
| {{- raise_exception( | |
| 'preserve_reasoning and preserve_thinking were both provided with conflicting values.' | |
| ) }} | |
| {%- endif %} | |
| {%- if preserve_reasoning is defined and preserve_reasoning is not none %} | |
| {%- set _preserve_thinking = preserve_reasoning %} | |
| {%- elif preserve_thinking is defined and preserve_thinking is not none %} | |
| {%- set _preserve_thinking = preserve_thinking %} | |
| {%- else %} | |
| {%- set _preserve_thinking = true %} | |
| {%- endif %} | |
| {%- set max_tool_arg_chars = | |
| max_tool_arg_chars if max_tool_arg_chars is defined else 0 | |
| %} | |
| {%- set max_tool_response_chars = | |
| max_tool_response_chars if max_tool_response_chars is defined else 0 | |
| %} | |
| {%- if max_tool_arg_chars is not number or max_tool_arg_chars < 0 %} | |
| {{- raise_exception('max_tool_arg_chars must be a non-negative number.') }} | |
| {%- endif %} | |
| {%- if max_tool_response_chars is not number or max_tool_response_chars < 0 %} | |
| {{- raise_exception('max_tool_response_chars must be a non-negative number.') }} | |
| {%- endif %} | |
| {%- if tools is defined and tools is not none and tools %} | |
| {%- if tools is string or tools is mapping or tools is not iterable %} | |
| {{- raise_exception('tools must be an iterable list of tool definitions.') }} | |
| {%- endif %} | |
| {%- set _has_tools = true %} | |
| {%- else %} | |
| {%- set _has_tools = false %} | |
| {%- endif %} | |
| {#- ------------------------------------------------------------------------- | |
| Resolve the tool-call wire format. | |
| OpenAI-compatible servers hand assistant tool calls back with | |
| `function.arguments` as a JSON *string*, not a mapping. The XML parameter | |
| form needs the individual key/value pairs, and a chat template cannot | |
| decode a JSON string: the standard chat-template environment provides | |
| `tojson` but no inverse, and no codepoint-to-character primitive, so a | |
| hand-rolled scanner could not decode \uXXXX escapes correctly. Guessing | |
| would silently corrupt tool arguments, which is worse than any error. | |
| So when the caller does not pin a format, render the whole prompt in the | |
| JSON tool-call form if any tool call in the history carries string | |
| arguments. That is lossless, needs no decoding, and keeps the system-prompt | |
| instructions and the rendered history in one consistent format. Histories | |
| whose arguments are all mappings still render as XML, byte-identically to | |
| tool_call_format='xml'. | |
| A caller that explicitly pins 'xml' still gets a hard error for string | |
| arguments, because that request cannot be honoured faithfully. | |
| ------------------------------------------------------------------------- -#} | |
| {%- set format_scan = namespace(has_json_string_arguments=false) %} | |
| {%- for message in messages %} | |
| {%- if message.role == 'assistant' | |
| and message.tool_calls is defined | |
| and message.tool_calls is not none | |
| and message.tool_calls | |
| and message.tool_calls is not string | |
| and message.tool_calls is not mapping | |
| and message.tool_calls is iterable %} | |
| {%- for tool_call in message.tool_calls %} | |
| {%- if tool_call.function is defined | |
| and tool_call.function is not none %} | |
| {%- set _tc = tool_call.function %} | |
| {%- else %} | |
| {%- set _tc = tool_call %} | |
| {%- endif %} | |
| {%- if _tc.arguments is defined | |
| and _tc.arguments is not none | |
| and _tc.arguments is string | |
| and _tc.arguments | trim | |
| and _tc.arguments | trim != '{}' %} | |
| {%- set format_scan.has_json_string_arguments = true %} | |
| {%- endif %} | |
| {%- endfor %} | |
| {%- endif %} | |
| {%- endfor %} | |
| {%- if _requested_tool_format == 'auto' %} | |
| {%- if format_scan.has_json_string_arguments %} | |
| {%- set _tool_format = 'json' %} | |
| {%- else %} | |
| {%- set _tool_format = 'xml' %} | |
| {%- endif %} | |
| {%- else %} | |
| {%- set _tool_format = _requested_tool_format %} | |
| {%- endif %} | |
| {%- set _thinking_enabled = enable_thinking %} | |
| {%- if auto_disable_thinking_with_tools and _has_tools %} | |
| {%- set _thinking_enabled = false %} | |
| {%- endif %} | |
| {#- Validate reasoning effort even when thinking is disabled. -#} | |
| {%- set _effort_raw = | |
| reasoning_effort if reasoning_effort is defined else 'xhigh' | |
| %} | |
| {%- if _effort_raw == 'high' or _effort_raw == 'xhigh' %} | |
| {%- set _reasoning_effort = 'xhigh' %} | |
| {%- elif _effort_raw == 'medium' %} | |
| {%- set _reasoning_effort = 'medium' %} | |
| {%- elif _effort_raw == 'low' %} | |
| {%- set _reasoning_effort = 'low' %} | |
| {%- else %} | |
| {{- raise_exception( | |
| 'Unexpected reasoning effort ' ~ _effort_raw ~ | |
| '. Supported values are high/xhigh, medium, and low.' | |
| ) }} | |
| {%- endif %} | |
| {%- set reasoning_instructions = '' %} | |
| {%- if _thinking_enabled %} | |
| {%- if _reasoning_effort == 'xhigh' %} | |
| {%- set reasoning_instructions = | |
| 'Reasoning effort is set to xhigh. Please think carefully through the task, validate key assumptions, consider plausible alternatives, and prioritize correctness, consistency, and clarity in the final answer.' | |
| %} | |
| {%- elif _reasoning_effort == 'low' %} | |
| {%- set reasoning_instructions = | |
| 'Reasoning effort is set to low. Keep your thinking brief and focused, moving directly to the conclusion without unnecessary elaboration.' | |
| %} | |
| {%- endif %} | |
| {%- endif %} | |
| {#- ------------------------------------------------------------------------- | |
| Content rendering | |
| ------------------------------------------------------------------------- -#} | |
| {%- set image_count = namespace(value=0) %} | |
| {%- set video_count = namespace(value=0) %} | |
| {%- macro render_content(content, do_vision_count, is_system_content=false) %} | |
| {%- if content is string %} | |
| {{- content }} | |
| {%- elif content is iterable and content is not mapping %} | |
| {%- for item in content %} | |
| {%- if item is not mapping %} | |
| {{- raise_exception( | |
| 'Content-list items must be mappings with a supported text, image, or video type.' | |
| ) }} | |
| {%- endif %} | |
| {%- set _item_type = item.type if 'type' in item else none %} | |
| {%- if _item_type is not none | |
| and _item_type not in ('text', 'image', 'image_url', 'video') %} | |
| {{- raise_exception( | |
| 'Unexpected content item type ' ~ _item_type ~ '.' | |
| ) }} | |
| {%- endif %} | |
| {%- set _is_image = | |
| _item_type == 'image' | |
| or _item_type == 'image_url' | |
| or 'image' in item | |
| or 'image_url' in item | |
| %} | |
| {%- set _is_video = | |
| _item_type == 'video' | |
| or 'video' in item | |
| %} | |
| {%- if _is_image and _is_video %} | |
| {{- raise_exception( | |
| 'A content item cannot contain both image and video data.' | |
| ) }} | |
| {%- elif _item_type == 'text' and (_is_image or _is_video) %} | |
| {{- raise_exception( | |
| 'A text content item cannot also contain image or video data.' | |
| ) }} | |
| {%- elif _is_image %} | |
| {%- if is_system_content %} | |
| {{- raise_exception( | |
| 'System and developer messages cannot contain images.' | |
| ) }} | |
| {%- endif %} | |
| {%- if do_vision_count %} | |
| {%- set image_count.value = image_count.value + 1 %} | |
| {%- endif %} | |
| {%- if add_vision_id %} | |
| {{- 'Picture ' ~ image_count.value ~ ': ' }} | |
| {%- endif %} | |
| {{- '<|vision_start|><|image_pad|><|vision_end|>' }} | |
| {%- elif _is_video %} | |
| {%- if is_system_content %} | |
| {{- raise_exception( | |
| 'System and developer messages cannot contain videos.' | |
| ) }} | |
| {%- endif %} | |
| {%- if do_vision_count %} | |
| {%- set video_count.value = video_count.value + 1 %} | |
| {%- endif %} | |
| {%- if add_vision_id %} | |
| {{- 'Video ' ~ video_count.value ~ ': ' }} | |
| {%- endif %} | |
| {{- '<|vision_start|><|video_pad|><|vision_end|>' }} | |
| {%- elif _item_type == 'text' or 'text' in item %} | |
| {%- if 'text' not in item or item.text is not string %} | |
| {{- raise_exception( | |
| 'Text content items must contain a string text field.' | |
| ) }} | |
| {%- endif %} | |
| {{- item.text }} | |
| {%- else %} | |
| {{- raise_exception( | |
| 'Unexpected item in content list. Expected text, image, or video content.' | |
| ) }} | |
| {%- endif %} | |
| {%- endfor %} | |
| {%- elif content is none or content is undefined %} | |
| {{- '' }} | |
| {%- else %} | |
| {{- raise_exception('Unexpected content type.') }} | |
| {%- endif %} | |
| {%- endmacro %} | |
| {#- ------------------------------------------------------------------------- | |
| Validate and merge leading system/developer messages | |
| ------------------------------------------------------------------------- -#} | |
| {%- set head = namespace(count=0, seen_non_system=false) %} | |
| {%- for message in messages %} | |
| {%- set _is_system = | |
| message.role == 'system' or message.role == 'developer' | |
| %} | |
| {%- if _is_system %} | |
| {%- if head.seen_non_system %} | |
| {{- raise_exception( | |
| 'System and developer messages must appear before all user, assistant, and tool messages.' | |
| ) }} | |
| {%- endif %} | |
| {%- set head.count = head.count + 1 %} | |
| {%- else %} | |
| {%- set head.seen_non_system = true %} | |
| {%- endif %} | |
| {%- endfor %} | |
| {%- set system_state = namespace(content='') %} | |
| {%- for message in messages[:head.count] %} | |
| {%- set _part = | |
| render_content(message.content, false, true) | trim | |
| %} | |
| {%- if _part %} | |
| {%- if system_state.content %} | |
| {%- set system_state.content = | |
| system_state.content ~ '\n\n' ~ _part | |
| %} | |
| {%- else %} | |
| {%- set system_state.content = _part %} | |
| {%- endif %} | |
| {%- endif %} | |
| {%- endfor %} | |
| {%- set _system_content = system_state.content %} | |
| {%- set _msgs = messages[head.count:] %} | |
| {#- ------------------------------------------------------------------------- | |
| System prompt and tool instructions | |
| ------------------------------------------------------------------------- -#} | |
| {%- if _has_tools %} | |
| {{- '<|im_start|>system\n' }} | |
| {%- if reasoning_instructions %} | |
| {{- reasoning_instructions ~ '\n\n' }} | |
| {%- endif %} | |
| {{- '# Tools\n\nYou have access to the following functions:\n\n<tools>' }} | |
| {%- for tool in tools %} | |
| {{- '\n' }} | |
| {{- tool | tojson }} | |
| {%- endfor %} | |
| {{- '\n</tools>' }} | |
| {%- if _tool_format == 'json' %} | |
| {{- '\n\nIf you choose to call a function ONLY reply in the following format with NO suffix:\n\n<tool_call>\n{"name": "example_function_name", "arguments": {"example_parameter_1": "value_1", "example_parameter_2": "This is the value for the second parameter"}}\n</tool_call>\n\n<IMPORTANT>\nReminder:\n- Function calls MUST follow the specified format: a single JSON object with "name" and "arguments" keys must be nested within <tool_call></tool_call> XML tags\n- Required parameters MUST be specified\n- You may provide optional reasoning for your function call in natural language BEFORE the function call, but NOT after\n- If there is no function call available, answer the question like normal with your current knowledge and do not tell the user about function calls\n</IMPORTANT>' }} | |
| {%- else %} | |
| {{- '\n\nIf you choose to call a function ONLY reply in the following format with NO suffix:\n\n<tool_call>\n<function=example_function_name>\n<parameter=example_parameter_1>\nvalue_1\n</parameter>\n<parameter=example_parameter_2>\nThis is the value for the second parameter\nthat can span\nmultiple lines\n</parameter>\n</function>\n</tool_call>\n\n<IMPORTANT>\nReminder:\n- Function calls MUST follow the specified format: an inner <function=...></function> block must be nested within <tool_call></tool_call> XML tags\n- Required parameters MUST be specified\n- You may provide optional reasoning for your function call in natural language BEFORE the function call, but NOT after\n- If there is no function call available, answer the question like normal with your current knowledge and do not tell the user about function calls\n</IMPORTANT>' }} | |
| {%- endif %} | |
| {%- if _system_content %} | |
| {{- '\n\n' ~ _system_content }} | |
| {%- endif %} | |
| {{- '<|im_end|>\n' }} | |
| {%- else %} | |
| {%- if _system_content %} | |
| {{- '<|im_start|>system\n' | |
| ~ (reasoning_instructions ~ '\n\n' if reasoning_instructions else '') | |
| ~ _system_content | |
| ~ '<|im_end|>\n' | |
| }} | |
| {%- elif reasoning_instructions %} | |
| {{- '<|im_start|>system\n' | |
| ~ reasoning_instructions | |
| ~ '<|im_end|>\n' | |
| }} | |
| {%- endif %} | |
| {%- endif %} | |
| {#- ------------------------------------------------------------------------- | |
| Find the last real user query | |
| ------------------------------------------------------------------------- -#} | |
| {%- set ns = namespace( | |
| multi_step_tool=true, | |
| last_query_index=(_msgs | length) - 1 | |
| ) %} | |
| {%- for message in _msgs[::-1] %} | |
| {%- set index = (_msgs | length - 1) - loop.index0 %} | |
| {%- if ns.multi_step_tool and message.role == 'user' %} | |
| {%- set _rendered_user = | |
| render_content(message.content, false) | trim | |
| %} | |
| {%- if not ( | |
| _rendered_user.startswith('<tool_response>') | |
| and _rendered_user.endswith('</tool_response>') | |
| ) %} | |
| {%- set ns.multi_step_tool = false %} | |
| {%- set ns.last_query_index = index %} | |
| {%- endif %} | |
| {%- endif %} | |
| {%- endfor %} | |
| {%- if ns.multi_step_tool %} | |
| {{- raise_exception('No user query found in messages.') }} | |
| {%- endif %} | |
| {#- ------------------------------------------------------------------------- | |
| Conversation rendering | |
| ------------------------------------------------------------------------- -#} | |
| {%- set history_state = namespace(previous_role='') %} | |
| {%- for message in _msgs %} | |
| {%- set content = | |
| render_content(message.content, true) | trim | |
| %} | |
| {%- if message.role == 'user' %} | |
| {{- '<|im_start|>user\n' | |
| ~ content | |
| ~ '<|im_end|>\n' | |
| }} | |
| {%- elif message.role == 'assistant' %} | |
| {%- set reasoning_content = '' %} | |
| {%- if message.reasoning_content is defined | |
| and message.reasoning_content is not none %} | |
| {%- if message.reasoning_content is string %} | |
| {%- set reasoning_content = message.reasoning_content %} | |
| {%- else %} | |
| {%- set reasoning_content = | |
| message.reasoning_content | string | |
| %} | |
| {%- endif %} | |
| {%- elif message.thinking is defined | |
| and message.thinking is not none %} | |
| {%- if message.thinking is string %} | |
| {%- set reasoning_content = message.thinking %} | |
| {%- else %} | |
| {%- set reasoning_content = | |
| message.thinking | string | |
| %} | |
| {%- endif %} | |
| {%- endif %} | |
| {%- set reasoning_content = reasoning_content | trim %} | |
| {#- Preserve the original invariant: when thinking is preserved, | |
| always reconstruct the thinking block, even when it is empty. -#} | |
| {%- if _preserve_thinking | |
| or loop.index0 > ns.last_query_index %} | |
| {{- '<|im_start|>assistant\n<think>\n' | |
| ~ reasoning_content | |
| ~ '\n</think>\n\n' | |
| ~ content | |
| }} | |
| {%- else %} | |
| {{- '<|im_start|>assistant\n' ~ content }} | |
| {%- endif %} | |
| {%- if message.tool_calls is defined | |
| and message.tool_calls is not none | |
| and message.tool_calls %} | |
| {%- if message.tool_calls is string | |
| or message.tool_calls is mapping | |
| or message.tool_calls is not iterable %} | |
| {{- raise_exception( | |
| 'assistant.tool_calls must be an iterable list of tool calls.' | |
| ) }} | |
| {%- endif %} | |
| {%- for tool_call in message.tool_calls %} | |
| {%- if tool_call.function is defined | |
| and tool_call.function is not none %} | |
| {%- set tc = tool_call.function %} | |
| {%- else %} | |
| {%- set tc = tool_call %} | |
| {%- endif %} | |
| {%- if tc.name is not defined | |
| or tc.name is none | |
| or tc.name is not string | |
| or not tc.name %} | |
| {{- raise_exception( | |
| 'Every tool call must have a non-empty string name.' | |
| ) }} | |
| {%- endif %} | |
| {%- set tc_name = tc.name %} | |
| {%- if _tool_format == 'json' %} | |
| {%- if loop.first %} | |
| {%- if content | trim %} | |
| {{- '\n\n<tool_call>\n' }} | |
| {%- else %} | |
| {{- '<tool_call>\n' }} | |
| {%- endif %} | |
| {%- else %} | |
| {{- '\n<tool_call>\n' }} | |
| {%- endif %} | |
| {%- set _json_arguments = '{}' %} | |
| {%- if tc.arguments is defined | |
| and tc.arguments is not none %} | |
| {%- if tc.arguments is mapping %} | |
| {%- set _json_arguments = | |
| tc.arguments | tojson | |
| %} | |
| {%- elif tc.arguments is string %} | |
| {%- set _raw_arguments = | |
| tc.arguments | trim | |
| %} | |
| {%- if _raw_arguments %} | |
| {%- if not ( | |
| _raw_arguments.startswith('{') | |
| and _raw_arguments.endswith('}') | |
| ) %} | |
| {{- raise_exception( | |
| 'JSON tool-call arguments must be a JSON object string.' | |
| ) }} | |
| {%- endif %} | |
| {%- set _json_arguments = | |
| _raw_arguments | |
| %} | |
| {%- endif %} | |
| {%- else %} | |
| {{- raise_exception( | |
| 'JSON tool-call arguments must be a mapping or a JSON object string.' | |
| ) }} | |
| {%- endif %} | |
| {%- endif %} | |
| {{- '{"name": ' }} | |
| {{- tc_name | tojson }} | |
| {{- ', "arguments": ' }} | |
| {{- _json_arguments }} | |
| {{- '}\n</tool_call>' }} | |
| {%- else %} | |
| {%- if loop.first %} | |
| {%- if content | trim %} | |
| {{- '\n\n<tool_call>\n<function=' | |
| ~ tc_name | |
| ~ '>\n' | |
| }} | |
| {%- else %} | |
| {{- '<tool_call>\n<function=' | |
| ~ tc_name | |
| ~ '>\n' | |
| }} | |
| {%- endif %} | |
| {%- else %} | |
| {{- '\n<tool_call>\n<function=' | |
| ~ tc_name | |
| ~ '>\n' | |
| }} | |
| {%- endif %} | |
| {%- if tc.arguments is defined | |
| and tc.arguments is not none %} | |
| {%- if tc.arguments is mapping %} | |
| {%- for args_name, args_value | |
| in tc.arguments | items %} | |
| {%- set _argument_name = | |
| args_name | string | |
| %} | |
| {{- '<parameter=' | |
| ~ _argument_name | |
| ~ '>\n' | |
| }} | |
| {#- Preserve strings verbatim. Serialize every | |
| other type as JSON so booleans and null stay | |
| true/false/null instead of True/False/None. -#} | |
| {%- if args_value is string %} | |
| {%- set _argument_value = | |
| args_value | |
| %} | |
| {%- else %} | |
| {%- set _argument_value = | |
| args_value | tojson | |
| %} | |
| {%- endif %} | |
| {%- if max_tool_arg_chars > 0 | |
| and _argument_value | length | |
| > max_tool_arg_chars %} | |
| {{- _argument_value[:max_tool_arg_chars] }} | |
| {{- '\n[TRUNCATED — original length ' | |
| ~ (_argument_value | length | string) | |
| ~ ' chars]' | |
| }} | |
| {%- else %} | |
| {{- _argument_value }} | |
| {%- endif %} | |
| {{- '\n</parameter>\n' }} | |
| {%- endfor %} | |
| {%- elif tc.arguments is string %} | |
| {%- set _raw_arguments = | |
| tc.arguments | trim | |
| %} | |
| {%- if _raw_arguments | |
| and _raw_arguments != '{}' %} | |
| {{- raise_exception( | |
| 'tool_call_format="xml" requires tool-call arguments to be mappings, but received a JSON string. Parse the JSON string into a mapping before applying the template, or leave tool_call_format unset so the template can select the JSON tool-call format automatically.' | |
| ) }} | |
| {%- endif %} | |
| {%- else %} | |
| {{- raise_exception( | |
| 'XML tool-call arguments must be a mapping. Parse JSON-string arguments before applying the template.' | |
| ) }} | |
| {%- endif %} | |
| {%- endif %} | |
| {{- '</function>\n</tool_call>' }} | |
| {%- endif %} | |
| {%- endfor %} | |
| {%- endif %} | |
| {{- '<|im_end|>\n' }} | |
| {%- elif message.role == 'tool' %} | |
| {%- if history_state.previous_role != 'tool' %} | |
| {{- '<|im_start|>user' }} | |
| {%- endif %} | |
| {%- if max_tool_response_chars > 0 | |
| and content | length > max_tool_response_chars %} | |
| {%- set content = | |
| content[:max_tool_response_chars] | |
| ~ '\n[TRUNCATED — original length ' | |
| ~ (content | length | string) | |
| ~ ' chars]' | |
| %} | |
| {%- endif %} | |
| {{- '\n<tool_response>\n' }} | |
| {{- content }} | |
| {{- '\n</tool_response>' }} | |
| {%- if loop.last %} | |
| {{- '<|im_end|>\n' }} | |
| {%- elif _msgs[loop.index0 + 1].role != 'tool' %} | |
| {{- '<|im_end|>\n' }} | |
| {%- endif %} | |
| {%- elif message.role == 'system' | |
| or message.role == 'developer' %} | |
| {{- raise_exception( | |
| 'System and developer messages must appear only at the beginning of the conversation.' | |
| ) }} | |
| {%- else %} | |
| {{- raise_exception( | |
| 'Unexpected message role ' ~ message.role ~ '.' | |
| ) }} | |
| {%- endif %} | |
| {%- set history_state.previous_role = message.role %} | |
| {%- endfor %} | |
| {#- ------------------------------------------------------------------------- | |
| Generation prompt | |
| ------------------------------------------------------------------------- -#} | |
| {%- if add_generation_prompt %} | |
| {{- '<|im_start|>assistant\n' }} | |
| {%- if not _thinking_enabled %} | |
| {{- '<think>\n\n</think>\n\n' }} | |
| {%- else %} | |
| {{- '<think>\n' }} | |
| {%- endif %} | |
| {%- endif %} |