Fixup tool calling
This commit is contained in:
+22
-14
@@ -223,10 +223,10 @@ struct HarnessConfig {
|
||||
DRH_DEFINE_TYPE_OPTIONAL(HarnessConfig, max_tool_iterations, verbose, depth)
|
||||
|
||||
struct FunctionCall {
|
||||
std::string name;
|
||||
std::string arguments;
|
||||
std::string name = "";
|
||||
std::string arguments = "";
|
||||
};
|
||||
DRH_DEFINE_TYPE_REQUIRED(FunctionCall, name, arguments)
|
||||
DRH_DEFINE_TYPE_OPTIONAL(FunctionCall, name, arguments)
|
||||
|
||||
// Manual registration for vector<FunctionCall> (cannot be auto-registered via macros)
|
||||
inline const auto json_register_vector_FunctionCall = []() {
|
||||
@@ -239,19 +239,20 @@ inline const auto json_register_vector_FunctionCall = []() {
|
||||
}();
|
||||
|
||||
struct ToolCall {
|
||||
std::string id;
|
||||
std::string type;
|
||||
FunctionCall function;
|
||||
size_t index;
|
||||
std::string id = "";
|
||||
std::string type = "";
|
||||
FunctionCall function = {};
|
||||
};
|
||||
DRH_DEFINE_TYPE_REQUIRED(ToolCall, id, type, function)
|
||||
DRH_DEFINE_TYPE_MIXED(ToolCall, (index), (id, type, function))
|
||||
|
||||
struct Message {
|
||||
std::string role;
|
||||
std::string content;
|
||||
std::string reasoning;
|
||||
std::string reasoning_content;
|
||||
std::string tool_call_id;
|
||||
std::vector<ToolCall> tool_calls;
|
||||
std::string role = "";
|
||||
std::string content = "";
|
||||
std::string reasoning = "";
|
||||
std::string reasoning_content = "";
|
||||
std::string tool_call_id = "";
|
||||
std::vector<ToolCall> tool_calls = {};
|
||||
|
||||
std::string dump(int indent = -1) const;
|
||||
};
|
||||
@@ -361,11 +362,18 @@ struct SkillToolParams {
|
||||
};
|
||||
DRH_DEFINE_TYPE_REQUIRED(SkillToolParams, name)
|
||||
|
||||
struct NestedMixedTest {
|
||||
std::string name = "";
|
||||
std::string arguments = "";
|
||||
};
|
||||
|
||||
DRH_DEFINE_TYPE_REQUIRED(NestedMixedTest, name, arguments)
|
||||
|
||||
// Test struct for json_to_field - has both primitive and custom type fields
|
||||
struct MixedFieldsStruct {
|
||||
std::string name;
|
||||
int count;
|
||||
FunctionCall func;
|
||||
NestedMixedTest func;
|
||||
};
|
||||
DRH_DEFINE_TYPE_MIXED(MixedFieldsStruct, (name, count, func), ())
|
||||
|
||||
|
||||
+22
-2
@@ -138,18 +138,37 @@ std::expected<Message, std::string> OllamaClient::chat(const std::vector<Message
|
||||
|
||||
auto partial_message = &chat_response->choices[0].delta;
|
||||
|
||||
//std::cerr << new_packet << std::endl;
|
||||
|
||||
total.content += partial_message->content;
|
||||
total.reasoning_content += partial_message->reasoning_content;
|
||||
total.reasoning += partial_message->reasoning;
|
||||
total.role += partial_message->role;
|
||||
total.tool_call_id += partial_message->tool_call_id;
|
||||
// FIXME:
|
||||
//total.tool_calls += partial_message->tool_calls;
|
||||
|
||||
std::string to_write = partial_message->content
|
||||
+ partial_message->reasoning_content
|
||||
+ partial_message->reasoning;
|
||||
|
||||
for (auto const& x : partial_message->tool_calls)
|
||||
{
|
||||
if (x.index < 100)
|
||||
{
|
||||
while (total.tool_calls.size() <= x.index)
|
||||
{
|
||||
total.tool_calls.push_back(ToolCall{x.index});
|
||||
}
|
||||
|
||||
to_write += x.function.name;
|
||||
to_write += x.function.arguments;
|
||||
|
||||
total.tool_calls[x.index].function.arguments += x.function.arguments;
|
||||
total.tool_calls[x.index].function.name += x.function.name;
|
||||
total.tool_calls[x.index].id += x.id;
|
||||
total.tool_calls[x.index].type += x.type;
|
||||
}
|
||||
}
|
||||
|
||||
std::string to_write2 = "";
|
||||
for (char const& c : to_write)
|
||||
{
|
||||
@@ -171,6 +190,7 @@ std::expected<Message, std::string> OllamaClient::chat(const std::vector<Message
|
||||
if (!response_result) {
|
||||
return std::unexpected(response_result.error());
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
//std::cerr << "Repsonse: " << response_buf << std::endl;
|
||||
//std::cerr << "Total Tokens: " << ret.usage.total_tokens << std::endl;
|
||||
//std::cerr << "Input Tokens: " << ret.usage.prompt_tokens << std::endl;
|
||||
|
||||
+1
-1
@@ -64,7 +64,7 @@ function message() {
|
||||
--arg name "$tool_name" \
|
||||
--argjson args "$tool_args" \
|
||||
'. + {
|
||||
"tool_calls": [{"id": "call_1", "type": "function", "function": {"name": $name, "arguments": $args}}],
|
||||
"tool_calls": [{"index":0, "id": "call_1", "type": "function", "function": {"name": $name, "arguments": $args}}],
|
||||
"content": null
|
||||
}')
|
||||
else
|
||||
|
||||
@@ -107,21 +107,3 @@ fi
|
||||
|
||||
echo "All MixedFieldsStruct tests passed!"
|
||||
|
||||
# ===== Deeply nested type error propagation test (issue 86) =====
|
||||
|
||||
# Test Message → vector<ToolCall> → FunctionCall error propagation
|
||||
# Verify that missing required field in deeply nested type produces proper error message
|
||||
OUTPUT=$("${DRHARNESS}" -R Message '{"role": "user", "tool_calls": [{"id": "call_1", "type": "function", "function": {"name": "test"}}]}')
|
||||
if [ "${OUTPUT}" != "error: field 'tool_calls': element 0: field 'function': missing required field: arguments" ]; then
|
||||
echo "FAIL: Message deeply nested error - expected 'error: field '\''tool_calls'\'': element 0: field '\''function'\'': missing required field: arguments', got '${OUTPUT}'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test Message → vector<ToolCall> → ToolCall missing required field
|
||||
OUTPUT=$("${DRHARNESS}" -R Message '{"role": "user", "tool_calls": [{"id": "call_1", "function": {"name": "test", "arguments": "{}"}}]}')
|
||||
if [ "${OUTPUT}" != "error: field 'tool_calls': element 0: missing required field: type" ]; then
|
||||
echo "FAIL: Message tool_calls missing type - expected 'error: field '\''tool_calls'\'': element 0: missing required field: type', got '${OUTPUT}'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "All deeply nested type tests passed (issue 86)!"
|
||||
|
||||
Reference in New Issue
Block a user