@brief Handle the openai chat completion request @param request the request @param send_response the send response @param send_streaming_response the send streaming response
| 1042 | ///@param send_response the send response |
| 1043 | ///@param send_streaming_response the send streaming response |
| 1044 | void RestHandler::handle_openai_chat_completion(const json& request, |
| 1045 | std::function<void(const json&)> send_response, |
| 1046 | StreamResponseCallback send_streaming_response, |
| 1047 | std::shared_ptr<CancellationToken> cancellation_token) { |
| 1048 | static std::string model_used_for_last_message = "model-faker"; |
| 1049 | try { |
| 1050 | // Extract OpenAI-style parameters |
| 1051 | json current_messages = request["messages"]; |
| 1052 | std::string model = request.value("model", current_model_tag); |
| 1053 | bool stream = request.value("stream", false); |
| 1054 | int length_limit = request.value("max_tokens", request.value("max_completion_tokens", 4096)); |
| 1055 | json tools = request.value("tools", json::array()); |
| 1056 | json options = request.value("options", json::object()); |
| 1057 | |
| 1058 | auto load_start_time = time_utils::now(); |
| 1059 | if (!ensure_model_loaded(model)) { |
| 1060 | json error_response = {{"error", "Failed to load " + model + " model!"}}; |
| 1061 | send_response(error_response); |
| 1062 | return; |
| 1063 | } |
| 1064 | auto load_end_time = time_utils::now(); |
| 1065 | |
| 1066 | configure_chat_engine_parameters(options, request); |
| 1067 | |
| 1068 | current_messages = normalize_messages(current_messages); |
| 1069 | current_messages = normalize_template(current_messages); |
| 1070 | |
| 1071 | // see if we can use prompt cache |
| 1072 | chat_meta_info_t meta_info; |
| 1073 | bool can_use_prompt_cache = false; |
| 1074 | if (model != model_used_for_last_message) { // switch models will clear context |
| 1075 | this->prompt_cache.update_message_checksum(current_messages); |
| 1076 | this->prompt_cache.update_tool_checksum(tools); |
| 1077 | model_used_for_last_message = model; |
| 1078 | } |
| 1079 | else { |
| 1080 | can_use_prompt_cache = prompt_cache.can_use_cache(current_messages, auto_chat_engine->get_chat_template_type(), tools); |
| 1081 | if (can_use_prompt_cache) { |
| 1082 | meta_info.restore_allowed = true; |
| 1083 | header_print("FLM", "Use cached prompt!"); |
| 1084 | } |
| 1085 | else { |
| 1086 | // cannot use cache, clear and re-insert all |
| 1087 | auto_chat_engine->clear_context(); |
| 1088 | } |
| 1089 | } |
| 1090 | |
| 1091 | if (model.starts_with("gemma4-it")) { |
| 1092 | current_messages = convert_tool_responses_gemma4(current_messages); |
| 1093 | } |
| 1094 | |
| 1095 | // std::cout << "FLM current_messages: \n" << current_messages.dump(4) << std::endl; |
| 1096 | |
| 1097 | lm_uniform_input_t uniformed_input; |
| 1098 | uniformed_input.messages = current_messages; |
| 1099 | uniformed_input.tools = tools; |
| 1100 | meta_info.load_duration = (uint64_t)time_utils::duration_ns(load_start_time, load_end_time).first; |
| 1101 | meta_info.max_prefill_len = this->prefill_chunk_len; |
no test coverage detected