Skip to content

Commit 62b8143

Browse files
pwilkinaldehir
andauthored
Fix structured outputs (#20223)
* Fix structured outputs * Update common/chat-auto-parser-generator.cpp Co-authored-by: Aldehir Rojas <hello@alde.dev> --------- Co-authored-by: Aldehir Rojas <hello@alde.dev>
1 parent d088d5b commit 62b8143

1 file changed

Lines changed: 14 additions & 8 deletions

File tree

common/chat-auto-parser-generator.cpp

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "chat-auto-parser.h"
22
#include "chat-peg-parser.h"
33
#include "chat.h"
4+
#include "common.h"
45
#include "json-schema-to-grammar.h"
56
#include "nlohmann/json.hpp"
67

@@ -51,13 +52,15 @@ common_chat_params peg_generator::generate_parser(const common_chat_template &
5152
bool has_tools =
5253
autoparser.tools.format.mode != tool_format::NONE && inputs.tools.is_array() && !inputs.tools.empty();
5354
std::string trigger_marker = !autoparser.tools.format.section_start.empty() ? autoparser.tools.format.section_start :
54-
autoparser.tools.format.per_call_start;
55-
bool include_grammar =
56-
has_tools && ((inputs.tool_choice == COMMON_CHAT_TOOL_CHOICE_AUTO && !trigger_marker.empty()) ||
57-
inputs.tool_choice == COMMON_CHAT_TOOL_CHOICE_REQUIRED);
55+
autoparser.tools.format.per_call_start;
56+
57+
bool has_response_format = !inputs.json_schema.empty() && inputs.json_schema.is_object();
58+
bool include_grammar = has_response_format || (has_tools &&
59+
((inputs.tool_choice == COMMON_CHAT_TOOL_CHOICE_AUTO && !trigger_marker.empty()) ||
60+
inputs.tool_choice == COMMON_CHAT_TOOL_CHOICE_REQUIRED));
5861

5962
if (include_grammar) {
60-
data.grammar_lazy = inputs.tool_choice == COMMON_CHAT_TOOL_CHOICE_AUTO;
63+
data.grammar_lazy = !has_response_format && inputs.tool_choice == COMMON_CHAT_TOOL_CHOICE_AUTO;
6164
data.grammar = build_grammar([&](const common_grammar_builder & builder) {
6265
foreach_function(inputs.tools, [&](const json & tool) {
6366
const auto & function = tool.at("function");
@@ -68,7 +71,7 @@ common_chat_params peg_generator::generate_parser(const common_chat_template &
6871
});
6972

7073
// Set grammar triggers based on tool section markers (fall back to per-call markers)
71-
if (data.grammar_lazy) { // only do triggers on lazy grammar
74+
if (data.grammar_lazy) {
7275
data.grammar_triggers = {
7376
{ COMMON_GRAMMAR_TRIGGER_TYPE_WORD, trigger_marker }
7477
};
@@ -104,8 +107,11 @@ common_peg_arena autoparser::build_parser(const templates_params & inputs) const
104107
bool has_response_format = inputs.json_schema.is_object() && !inputs.json_schema.empty();
105108

106109
if (has_response_format) {
107-
return ctx.reasoning_parser + p.space() +
108-
p.content(p.schema(p.json(), "response-format", inputs.json_schema)) + p.end();
110+
auto response_format = p.rule("response-format", p.content(p.schema(p.json(), "response-format-schema", inputs.json_schema)));
111+
return ctx.reasoning_parser + p.space() + p.choice({
112+
p.literal("```json") + p.space() + response_format + p.space() + p.literal("```"),
113+
response_format
114+
}) + p.end();
109115
}
110116

111117
if (has_tools && inputs.tool_choice != COMMON_CHAT_TOOL_CHOICE_NONE && jinja_caps.supports_tool_calls) {

0 commit comments

Comments
 (0)