| 462 | } |
| 463 | |
| 464 | analyze_content::analyze_content(const common_chat_template & tmpl, const analyze_reasoning & reasoning) |
| 465 | : analyze_base(tmpl) { |
| 466 | LOG_DBG(ANSI_ORANGE "Phase 2: Content analysis\n" ANSI_RESET); |
| 467 | |
| 468 | json assistant_content_only = json{ |
| 469 | { "role", "assistant" }, |
| 470 | { "content", ASSISTANT_MSG } |
| 471 | }; |
| 472 | |
| 473 | json assistant_with_tools = json{ |
| 474 | { "role", "assistant" }, |
| 475 | { "content", "" }, |
| 476 | { "tool_calls", json::array({ build_tool_call("test_func", json{ { "arg1", "value1" } }) }) } |
| 477 | }; |
| 478 | |
| 479 | json assistant_with_reasoning = json{ |
| 480 | { "role", "assistant" }, |
| 481 | { "content", "" }, |
| 482 | { "reasoning_content", THINKING_CONTENT } |
| 483 | }; |
| 484 | |
| 485 | template_params params_content_only; |
| 486 | params_content_only.messages = json::array({ user_msg, assistant_content_only }); |
| 487 | params_content_only.add_generation_prompt = false; |
| 488 | params_content_only.enable_thinking = true; |
| 489 | params_content_only.tools = tools; |
| 490 | |
| 491 | auto comparison_with_tools = compare_variants(tmpl, params_content_only, [&](template_params & p) { |
| 492 | p.messages = json::array({ user_msg, assistant_with_tools }); |
| 493 | }); |
| 494 | |
| 495 | auto comparison_with_reasoning = compare_variants(tmpl, params_content_only, [&](template_params & p) { |
| 496 | p.messages = json::array({ user_msg, assistant_with_reasoning }); |
| 497 | }); |
| 498 | |
| 499 | if (!comparison_with_tools || !comparison_with_reasoning) { |
| 500 | LOG_DBG(ANSI_ORANGE "%s: Template application failed\n" ANSI_RESET, __func__); |
| 501 | return; |
| 502 | } |
| 503 | |
| 504 | const auto & diff_tools = comparison_with_tools->diff; |
| 505 | const auto & diff_reasoning = comparison_with_reasoning->diff; |
| 506 | |
| 507 | std::string response = ASSISTANT_MSG; |
| 508 | |
| 509 | bool found_plain_content = false; |
| 510 | if (trim_whitespace(diff_tools.left) == response) { |
| 511 | auto parser = build_tagged_peg_parser([&](common_peg_parser_builder & p) { |
| 512 | return p.space() + diff_reasoning.left + p.space() + p.optional(p.marker()) + p.space() + p.end(); |
| 513 | }); |
| 514 | if (parser.parse_and_extract(diff_reasoning.left).result.success()) { |
| 515 | // We only have the content text in the diff (possibly with a stray EOG marker), so no markers |
| 516 | mode = content_mode::PLAIN; |
| 517 | found_plain_content = true; |
| 518 | } else if (reasoning.mode != reasoning_mode::NONE && !reasoning.end.empty()) { |
| 519 | auto post_reasoning_parser = build_tagged_peg_parser([&](common_peg_parser_builder & p) { |
| 520 | return p.literal(reasoning.end) + p.space() + p.literal(response); |
| 521 | }); |
nothing calls this directly
no test coverage detected