Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmake/deps.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pybind11;https://github.com/pybind/pybind11/archive/refs/tags/v2.13.6.zip;f78029
googletest;https://github.com/google/googletest/archive/530d5c8c84abd2a46f38583ee817743c9b3a42b4.zip;5e3a61db2aa975cfd0f97ba92c818744e7fa7034
microsoft_wil;https://github.com/microsoft/wil/archive/refs/tags/v1.0.230629.1.zip;e4a542a323c070376f7c2d1973d0f7ddbc1d2fa5
directx_headers;https://github.com/microsoft/DirectX-Headers/archive/refs/tags/v1.613.1.zip;47653509a3371eabb156360f42faf582f314bf2e
onnxruntime_extensions;https://github.com/microsoft/onnxruntime-extensions.git;60687b12b9de56df9a702a0e548eacc26836fab9
onnxruntime_extensions;https://github.com/microsoft/onnxruntime-extensions.git;bd0e21c11187e0b8a2385d1c61122a4d259a53a0

# These two dependencies are for the optional constrained decoding feature (USE_GUIDANCE)
llguidance;https://github.com/microsoft/llguidance.git;94fa39128ef184ffeda33845f6d333f332a34b4d
Expand Down
9 changes: 8 additions & 1 deletion src/models/model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -419,8 +419,15 @@ std::string Tokenizer::Decode(std::span<const int32_t> tokens) const {
}

std::string Tokenizer::ApplyChatTemplate(const char* template_str, const char* messages, const char* tools, bool add_generation_prompt) const {
return ApplyChatTemplateWithOptions(template_str, messages, tools, nullptr, add_generation_prompt);
Comment thread
jennyf19 marked this conversation as resolved.
Outdated
}

std::string Tokenizer::ApplyChatTemplateWithOptions(const char* template_str, const char* messages, const char* tools,
const char* template_kwargs, bool add_generation_prompt) const {
ort_extensions::OrtxObjectPtr<OrtxTensorResult> templated_text;
CheckResult(OrtxApplyChatTemplate(tokenizer_, template_str, messages, tools, templated_text.ToBeAssigned(), add_generation_prompt, false /*tokenize*/));
CheckResult(OrtxApplyChatTemplateWithOptions(tokenizer_, template_str, messages, tools, template_kwargs,
templated_text.ToBeAssigned(), add_generation_prompt,
false /*tokenize*/));

ort_extensions::OrtxObjectPtr<OrtxTensor> tensor;
CheckResult(OrtxTensorResultGetAt(templated_text.get(), 0, tensor.ToBeAssigned()));
Expand Down
2 changes: 2 additions & 0 deletions src/models/model.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ struct Tokenizer : std::enable_shared_from_this<Tokenizer>, LeakChecked<Tokenize
std::vector<int32_t> Encode(const char* text) const;
std::string Decode(std::span<const int32_t> tokens) const;
std::string ApplyChatTemplate(const char* template_str, const char* messages, const char* tools, bool add_generation_prompt) const;
std::string ApplyChatTemplateWithOptions(const char* template_str, const char* messages, const char* tools,
const char* template_kwargs, bool add_generation_prompt) const;

std::vector<int32_t> EncodeBatch(std::span<const std::string> strings) const;
std::shared_ptr<Tensor> EncodeBatch(std::span<const char*> strings) const;
Expand Down
8 changes: 7 additions & 1 deletion src/ort_genai.h
Original file line number Diff line number Diff line change
Expand Up @@ -415,8 +415,14 @@ struct OgaTokenizer : OgaAbstract {
}

OgaString ApplyChatTemplate(const char* template_str, const char* messages, const char* tools, bool add_generation_prompt) const {
return ApplyChatTemplateWithOptions(template_str, messages, tools, nullptr, add_generation_prompt);
}

OgaString ApplyChatTemplateWithOptions(const char* template_str, const char* messages, const char* tools,
const char* template_kwargs, bool add_generation_prompt) const {
const char* p{};
OgaCheckResult(OgaTokenizerApplyChatTemplate(this, template_str, messages, tools, add_generation_prompt, &p));
OgaCheckResult(OgaTokenizerApplyChatTemplateWithOptions(this, template_str, messages, tools, template_kwargs,
add_generation_prompt, &p));
return p;
}

Expand Down
11 changes: 10 additions & 1 deletion src/ort_genai_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1035,8 +1035,17 @@ OgaResult* OGA_API_CALL OgaTokenizerDecode(const OgaTokenizer* tokenizer, const
}

OgaResult* OGA_API_CALL OgaTokenizerApplyChatTemplate(const OgaTokenizer* tokenizer, const char* template_str, const char* messages, const char* tools, bool add_generation_prompt, const char** out_string) {
return OgaTokenizerApplyChatTemplateWithOptions(tokenizer, template_str, messages, tools, nullptr,
add_generation_prompt, out_string);
}

OgaResult* OGA_API_CALL OgaTokenizerApplyChatTemplateWithOptions(const OgaTokenizer* tokenizer, const char* template_str,
const char* messages, const char* tools,
const char* template_kwargs, bool add_generation_prompt,
const char** out_string) {
OGA_TRY
*out_string = AllocOgaString(tokenizer->ApplyChatTemplate(template_str, messages, tools, add_generation_prompt));
*out_string = AllocOgaString(tokenizer->ApplyChatTemplateWithOptions(template_str, messages, tools,
template_kwargs, add_generation_prompt));
return nullptr;
OGA_CATCH
}
Expand Down
14 changes: 14 additions & 0 deletions src/ort_genai_c.h
Original file line number Diff line number Diff line change
Expand Up @@ -989,6 +989,20 @@ OGA_EXPORT OgaResult* OGA_API_CALL OgaProcessorDecode(const OgaMultiModalProcess
*/
OGA_EXPORT OgaResult* OGA_API_CALL OgaTokenizerApplyChatTemplate(const OgaTokenizer*, const char* template_str, const char* messages, const char* tools, bool add_generation_prompt, const char** out_string);

/**
* @brief Applies a chat template to input messages with additional template context values.
*
* \param[in] tokenizer OgaTokenizer used for template processing.
* \param[in] template_str Null-terminated string representing the chat template. Use nullptr to fall back to the default chat template from the tokenizer config.
* \param[in] messages Null-terminated string containing the input messages to be processed.
* \param[in] tools Null-terminated string containing the chat function calls if any. Use nullptr if none.
* \param[in] template_kwargs Null-terminated JSON object containing additional template context values. Use nullptr if none.
* \param[in] add_generation_prompt Indicates whether to add a generation prompt to the output.
* \param[out] out_string Pointer to where the output will be stored. The returned pointer must be freed with OgaDestroyString.
* \return OgaResult* containing the error message if the function fails.
*/
OGA_EXPORT OgaResult* OGA_API_CALL OgaTokenizerApplyChatTemplateWithOptions(const OgaTokenizer*, const char* template_str, const char* messages, const char* tools, const char* template_kwargs, bool add_generation_prompt, const char** out_string);

/** OgaTokenizerStream is to decoded token strings incrementally, one token at a time.
*/
OGA_EXPORT OgaResult* OGA_API_CALL OgaCreateTokenizerStream(const OgaTokenizer*, OgaTokenizerStream** out);
Expand Down
15 changes: 15 additions & 0 deletions test/c_api_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,21 @@ TEST(CAPITests, ChatTemplate) {
auto out_string = tokenizer->ApplyChatTemplate(chat_template, messages_json, nullptr, true);
ASSERT_STREQ(expected_output, out_string);

const char* kwargs_template =
"{% if enable_thinking is defined and not enable_thinking %}NO_THINK{% else %}THINK{% endif %}"
"|{{ reasoning_effort }}|{{ level }}";
const char* template_kwargs =
R"({"enable_thinking":false,"reasoning_effort":"low","level":2})";
auto kwargs_output = tokenizer->ApplyChatTemplateWithOptions(
kwargs_template, messages_json, nullptr, template_kwargs, true);
ASSERT_STREQ("NO_THINK|low|2", kwargs_output);

auto legacy_output = tokenizer->ApplyChatTemplate(
"{{ messages[0].content }}", messages_json, nullptr, true);
auto null_options_output = tokenizer->ApplyChatTemplateWithOptions(
"{{ messages[0].content }}", messages_json, nullptr, nullptr, true);
ASSERT_STREQ(legacy_output, null_options_output);

#endif
}

Expand Down
Loading