1
0

chat-peg-parser.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. #include "chat-peg-parser.h"
  2. #include <nlohmann/json.hpp>
  3. using json = nlohmann::json;
  4. static std::string_view trim_trailing_space(std::string_view sv, int max = -1) {
  5. int count = 0;
  6. while (!sv.empty() && std::isspace(static_cast<unsigned char>(sv.back()))) {
  7. if (max != -1 && count <= max) {
  8. break;
  9. }
  10. sv.remove_suffix(1);
  11. count++;
  12. }
  13. return sv;
  14. }
  15. void common_chat_peg_mapper::from_ast(const common_peg_ast_arena & arena, const common_peg_parse_result & result) {
  16. arena.visit(result, [this](const common_peg_ast_node & node) {
  17. map(node);
  18. });
  19. }
  20. void common_chat_peg_mapper::map(const common_peg_ast_node & node) {
  21. bool is_reasoning = node.tag == common_chat_peg_builder::REASONING;
  22. bool is_content = node.tag == common_chat_peg_builder::CONTENT;
  23. if (is_reasoning) {
  24. result.reasoning_content = std::string(trim_trailing_space(node.text));
  25. }
  26. if (is_content) {
  27. result.content = std::string(trim_trailing_space(node.text));
  28. }
  29. }
  30. void common_chat_peg_native_mapper::map(const common_peg_ast_node & node) {
  31. common_chat_peg_mapper::map(node);
  32. bool is_tool_open = node.tag == common_chat_peg_native_builder::TOOL_OPEN;
  33. bool is_tool_name = node.tag == common_chat_peg_native_builder::TOOL_NAME;
  34. bool is_tool_id = node.tag == common_chat_peg_native_builder::TOOL_ID;
  35. bool is_tool_args = node.tag == common_chat_peg_native_builder::TOOL_ARGS;
  36. if (is_tool_open) {
  37. result.tool_calls.emplace_back();
  38. current_tool = &result.tool_calls.back();
  39. }
  40. if (is_tool_id && current_tool) {
  41. current_tool->id = std::string(trim_trailing_space(node.text));
  42. }
  43. if (is_tool_name && current_tool) {
  44. current_tool->name = std::string(trim_trailing_space(node.text));
  45. }
  46. if (is_tool_args && current_tool) {
  47. current_tool->arguments = std::string(trim_trailing_space(node.text));
  48. }
  49. }
  50. void common_chat_peg_constructed_mapper::map(const common_peg_ast_node & node) {
  51. common_chat_peg_mapper::map(node);
  52. bool is_tool_open = node.tag == common_chat_peg_constructed_builder::TOOL_OPEN;
  53. bool is_tool_name = node.tag == common_chat_peg_constructed_builder::TOOL_NAME;
  54. bool is_tool_close = node.tag == common_chat_peg_constructed_builder::TOOL_CLOSE;
  55. bool is_arg_open = node.tag == common_chat_peg_constructed_builder::TOOL_ARG_OPEN;
  56. bool is_arg_close = node.tag == common_chat_peg_constructed_builder::TOOL_ARG_CLOSE;
  57. bool is_arg_name = node.tag == common_chat_peg_constructed_builder::TOOL_ARG_NAME;
  58. bool is_arg_string = node.tag == common_chat_peg_constructed_builder::TOOL_ARG_STRING_VALUE;
  59. bool is_arg_json = node.tag == common_chat_peg_constructed_builder::TOOL_ARG_JSON_VALUE;
  60. if (is_tool_open) {
  61. result.tool_calls.emplace_back();
  62. current_tool = &result.tool_calls.back();
  63. arg_count = 0;
  64. }
  65. if (is_tool_name) {
  66. current_tool->name = std::string(node.text);
  67. current_tool->arguments = "{";
  68. }
  69. if (is_arg_open) {
  70. needs_closing_quote = false;
  71. }
  72. if (is_arg_name && current_tool) {
  73. if (arg_count > 0) {
  74. current_tool->arguments += ",";
  75. }
  76. current_tool->arguments += json(trim_trailing_space(node.text)).dump() + ":";
  77. ++arg_count;
  78. }
  79. if (is_arg_string && current_tool) {
  80. // Serialize to JSON, but exclude the end quote
  81. std::string dumped = json(trim_trailing_space(node.text)).dump();
  82. current_tool->arguments += dumped.substr(0, dumped.size() - 1);
  83. needs_closing_quote = true;
  84. }
  85. if (is_arg_close && current_tool) {
  86. if (needs_closing_quote) {
  87. current_tool->arguments += "\"";
  88. needs_closing_quote = false;
  89. }
  90. }
  91. if (is_arg_json && current_tool) {
  92. current_tool->arguments += std::string(trim_trailing_space(node.text));
  93. }
  94. if (is_tool_close && current_tool) {
  95. if (needs_closing_quote) {
  96. current_tool->arguments += "\"";
  97. needs_closing_quote = false;
  98. }
  99. current_tool->arguments += "}";
  100. }
  101. }