mirror of
				https://github.com/meilisearch/meilisearch.git
				synced 2025-10-31 16:06:31 +00:00 
			
		
		
		
	Make sure template errors are reported to the LLM and front-end without panicking
This commit is contained in:
		| @@ -394,6 +394,7 @@ UnimplementedExternalFunctionCalling           , InvalidRequest       , NOT_IMPL | |||||||
| UnimplementedNonStreamingChatCompletions       , InvalidRequest       , NOT_IMPLEMENTED ; | UnimplementedNonStreamingChatCompletions       , InvalidRequest       , NOT_IMPLEMENTED ; | ||||||
| UnimplementedMultiChoiceChatCompletions        , InvalidRequest       , NOT_IMPLEMENTED ; | UnimplementedMultiChoiceChatCompletions        , InvalidRequest       , NOT_IMPLEMENTED ; | ||||||
| ChatNotFound                                   , InvalidRequest       , NOT_FOUND   ; | ChatNotFound                                   , InvalidRequest       , NOT_FOUND   ; | ||||||
|  | InvalidChatSettingDocumentTemplate             , InvalidRequest       , BAD_REQUEST ; | ||||||
| InvalidChatCompletionOrgId                     , InvalidRequest       , BAD_REQUEST ; | InvalidChatCompletionOrgId                     , InvalidRequest       , BAD_REQUEST ; | ||||||
| InvalidChatCompletionProjectId                 , InvalidRequest       , BAD_REQUEST ; | InvalidChatCompletionProjectId                 , InvalidRequest       , BAD_REQUEST ; | ||||||
| InvalidChatCompletionApiVersion                , InvalidRequest       , BAD_REQUEST ; | InvalidChatCompletionApiVersion                , InvalidRequest       , BAD_REQUEST ; | ||||||
|   | |||||||
| @@ -646,7 +646,7 @@ async fn handle_meili_tools( | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         let result = match serde_json::from_str(&call.function.arguments) { |         let result = match serde_json::from_str(&call.function.arguments) { | ||||||
|             Ok(SearchInIndexParameters { index_uid, q }) => process_search_request( |             Ok(SearchInIndexParameters { index_uid, q }) => match process_search_request( | ||||||
|                 index_scheduler, |                 index_scheduler, | ||||||
|                 auth_ctrl.clone(), |                 auth_ctrl.clone(), | ||||||
|                 search_queue, |                 search_queue, | ||||||
| @@ -655,7 +655,14 @@ async fn handle_meili_tools( | |||||||
|                 q, |                 q, | ||||||
|             ) |             ) | ||||||
|             .await |             .await | ||||||
|             .map_err(|e| e.to_string()), |             { | ||||||
|  |                 Ok(output) => Ok(output), | ||||||
|  |                 Err(err) => { | ||||||
|  |                     let error_text = err.to_string(); | ||||||
|  |                     tx.send_error(&StreamErrorEvent::from_response_error(err)).await?; | ||||||
|  |                     Err(error_text) | ||||||
|  |                 } | ||||||
|  |             }, | ||||||
|             Err(err) => Err(err.to_string()), |             Err(err) => Err(err.to_string()), | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
| @@ -664,7 +671,6 @@ async fn handle_meili_tools( | |||||||
|                 if report_sources { |                 if report_sources { | ||||||
|                     tx.report_sources(resp.clone(), &call.id, &documents).await?; |                     tx.report_sources(resp.clone(), &call.id, &documents).await?; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 text |                 text | ||||||
|             } |             } | ||||||
|             Err(err) => err, |             Err(err) => err, | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
| use async_openai::error::{ApiError, OpenAIError}; | use async_openai::error::{ApiError, OpenAIError}; | ||||||
| use async_openai::reqwest_eventsource::Error as EventSourceError; | use async_openai::reqwest_eventsource::Error as EventSourceError; | ||||||
|  | use meilisearch_types::error::ResponseError; | ||||||
| use serde::{Deserialize, Serialize}; | use serde::{Deserialize, Serialize}; | ||||||
| use uuid::Uuid; | use uuid::Uuid; | ||||||
|  |  | ||||||
| @@ -53,12 +54,13 @@ pub struct StreamError { | |||||||
| } | } | ||||||
|  |  | ||||||
| impl StreamErrorEvent { | impl StreamErrorEvent { | ||||||
|  |     const ERROR_TYPE: &str = "error"; | ||||||
|  |  | ||||||
|     pub async fn from_openai_error(error: OpenAIError) -> Result<Self, reqwest::Error> { |     pub async fn from_openai_error(error: OpenAIError) -> Result<Self, reqwest::Error> { | ||||||
|         let error_type = "error".to_string(); |  | ||||||
|         match error { |         match error { | ||||||
|             OpenAIError::Reqwest(e) => Ok(StreamErrorEvent { |             OpenAIError::Reqwest(e) => Ok(StreamErrorEvent { | ||||||
|                 event_id: Uuid::new_v4().to_string(), |                 event_id: Uuid::new_v4().to_string(), | ||||||
|                 r#type: error_type, |                 r#type: Self::ERROR_TYPE.to_string(), | ||||||
|                 error: StreamError { |                 error: StreamError { | ||||||
|                     r#type: "internal_reqwest_error".to_string(), |                     r#type: "internal_reqwest_error".to_string(), | ||||||
|                     code: Some("internal".to_string()), |                     code: Some("internal".to_string()), | ||||||
| @@ -69,7 +71,7 @@ impl StreamErrorEvent { | |||||||
|             }), |             }), | ||||||
|             OpenAIError::ApiError(ApiError { message, r#type, param, code }) => { |             OpenAIError::ApiError(ApiError { message, r#type, param, code }) => { | ||||||
|                 Ok(StreamErrorEvent { |                 Ok(StreamErrorEvent { | ||||||
|                     r#type: error_type, |                     r#type: Self::ERROR_TYPE.to_string(), | ||||||
|                     event_id: Uuid::new_v4().to_string(), |                     event_id: Uuid::new_v4().to_string(), | ||||||
|                     error: StreamError { |                     error: StreamError { | ||||||
|                         r#type: r#type.unwrap_or_else(|| "unknown".to_string()), |                         r#type: r#type.unwrap_or_else(|| "unknown".to_string()), | ||||||
| @@ -82,7 +84,7 @@ impl StreamErrorEvent { | |||||||
|             } |             } | ||||||
|             OpenAIError::JSONDeserialize(error) => Ok(StreamErrorEvent { |             OpenAIError::JSONDeserialize(error) => Ok(StreamErrorEvent { | ||||||
|                 event_id: Uuid::new_v4().to_string(), |                 event_id: Uuid::new_v4().to_string(), | ||||||
|                 r#type: error_type, |                 r#type: Self::ERROR_TYPE.to_string(), | ||||||
|                 error: StreamError { |                 error: StreamError { | ||||||
|                     r#type: "json_deserialize_error".to_string(), |                     r#type: "json_deserialize_error".to_string(), | ||||||
|                     code: Some("internal".to_string()), |                     code: Some("internal".to_string()), | ||||||
| @@ -100,7 +102,7 @@ impl StreamErrorEvent { | |||||||
|  |  | ||||||
|                     Ok(StreamErrorEvent { |                     Ok(StreamErrorEvent { | ||||||
|                         event_id: Uuid::new_v4().to_string(), |                         event_id: Uuid::new_v4().to_string(), | ||||||
|                         r#type: error_type, |                         r#type: Self::ERROR_TYPE.to_string(), | ||||||
|                         error: StreamError { r#type, code, message, param, event_id: None }, |                         error: StreamError { r#type, code, message, param, event_id: None }, | ||||||
|                     }) |                     }) | ||||||
|                 } |                 } | ||||||
| @@ -111,13 +113,13 @@ impl StreamErrorEvent { | |||||||
|  |  | ||||||
|                     Ok(StreamErrorEvent { |                     Ok(StreamErrorEvent { | ||||||
|                         event_id: Uuid::new_v4().to_string(), |                         event_id: Uuid::new_v4().to_string(), | ||||||
|                         r#type: error_type, |                         r#type: Self::ERROR_TYPE.to_string(), | ||||||
|                         error: StreamError { r#type, code, message, param, event_id: None }, |                         error: StreamError { r#type, code, message, param, event_id: None }, | ||||||
|                     }) |                     }) | ||||||
|                 } |                 } | ||||||
|                 EventSourceError::Utf8(error) => Ok(StreamErrorEvent { |                 EventSourceError::Utf8(error) => Ok(StreamErrorEvent { | ||||||
|                     event_id: Uuid::new_v4().to_string(), |                     event_id: Uuid::new_v4().to_string(), | ||||||
|                     r#type: error_type, |                     r#type: Self::ERROR_TYPE.to_string(), | ||||||
|                     error: StreamError { |                     error: StreamError { | ||||||
|                         r#type: "invalid_utf8_error".to_string(), |                         r#type: "invalid_utf8_error".to_string(), | ||||||
|                         code: None, |                         code: None, | ||||||
| @@ -128,7 +130,7 @@ impl StreamErrorEvent { | |||||||
|                 }), |                 }), | ||||||
|                 EventSourceError::Parser(error) => Ok(StreamErrorEvent { |                 EventSourceError::Parser(error) => Ok(StreamErrorEvent { | ||||||
|                     event_id: Uuid::new_v4().to_string(), |                     event_id: Uuid::new_v4().to_string(), | ||||||
|                     r#type: error_type, |                     r#type: Self::ERROR_TYPE.to_string(), | ||||||
|                     error: StreamError { |                     error: StreamError { | ||||||
|                         r#type: "parser_error".to_string(), |                         r#type: "parser_error".to_string(), | ||||||
|                         code: None, |                         code: None, | ||||||
| @@ -139,7 +141,7 @@ impl StreamErrorEvent { | |||||||
|                 }), |                 }), | ||||||
|                 EventSourceError::Transport(error) => Ok(StreamErrorEvent { |                 EventSourceError::Transport(error) => Ok(StreamErrorEvent { | ||||||
|                     event_id: Uuid::new_v4().to_string(), |                     event_id: Uuid::new_v4().to_string(), | ||||||
|                     r#type: error_type, |                     r#type: Self::ERROR_TYPE.to_string(), | ||||||
|                     error: StreamError { |                     error: StreamError { | ||||||
|                         r#type: "transport_error".to_string(), |                         r#type: "transport_error".to_string(), | ||||||
|                         code: None, |                         code: None, | ||||||
| @@ -150,7 +152,7 @@ impl StreamErrorEvent { | |||||||
|                 }), |                 }), | ||||||
|                 EventSourceError::InvalidLastEventId(message) => Ok(StreamErrorEvent { |                 EventSourceError::InvalidLastEventId(message) => Ok(StreamErrorEvent { | ||||||
|                     event_id: Uuid::new_v4().to_string(), |                     event_id: Uuid::new_v4().to_string(), | ||||||
|                     r#type: error_type, |                     r#type: Self::ERROR_TYPE.to_string(), | ||||||
|                     error: StreamError { |                     error: StreamError { | ||||||
|                         r#type: "invalid_last_event_id".to_string(), |                         r#type: "invalid_last_event_id".to_string(), | ||||||
|                         code: None, |                         code: None, | ||||||
| @@ -161,7 +163,7 @@ impl StreamErrorEvent { | |||||||
|                 }), |                 }), | ||||||
|                 EventSourceError::StreamEnded => Ok(StreamErrorEvent { |                 EventSourceError::StreamEnded => Ok(StreamErrorEvent { | ||||||
|                     event_id: Uuid::new_v4().to_string(), |                     event_id: Uuid::new_v4().to_string(), | ||||||
|                     r#type: error_type, |                     r#type: Self::ERROR_TYPE.to_string(), | ||||||
|                     error: StreamError { |                     error: StreamError { | ||||||
|                         r#type: "stream_ended".to_string(), |                         r#type: "stream_ended".to_string(), | ||||||
|                         code: None, |                         code: None, | ||||||
| @@ -173,7 +175,7 @@ impl StreamErrorEvent { | |||||||
|             }, |             }, | ||||||
|             OpenAIError::InvalidArgument(message) => Ok(StreamErrorEvent { |             OpenAIError::InvalidArgument(message) => Ok(StreamErrorEvent { | ||||||
|                 event_id: Uuid::new_v4().to_string(), |                 event_id: Uuid::new_v4().to_string(), | ||||||
|                 r#type: error_type, |                 r#type: Self::ERROR_TYPE.to_string(), | ||||||
|                 error: StreamError { |                 error: StreamError { | ||||||
|                     r#type: "invalid_argument".to_string(), |                     r#type: "invalid_argument".to_string(), | ||||||
|                     code: None, |                     code: None, | ||||||
| @@ -184,4 +186,19 @@ impl StreamErrorEvent { | |||||||
|             }), |             }), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     pub fn from_response_error(error: ResponseError) -> Self { | ||||||
|  |         let ResponseError { code, message, .. } = error; | ||||||
|  |         StreamErrorEvent { | ||||||
|  |             event_id: Uuid::new_v4().to_string(), | ||||||
|  |             r#type: Self::ERROR_TYPE.to_string(), | ||||||
|  |             error: StreamError { | ||||||
|  |                 r#type: "response_error".to_string(), | ||||||
|  |                 code: Some(code.as_str().to_string()), | ||||||
|  |                 message, | ||||||
|  |                 param: None, | ||||||
|  |                 event_id: None, | ||||||
|  |             }, | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ use async_openai::types::{ | |||||||
|     FunctionCall, FunctionCallStream, Role, |     FunctionCall, FunctionCallStream, Role, | ||||||
| }; | }; | ||||||
| use bumpalo::Bump; | use bumpalo::Bump; | ||||||
| use meilisearch_types::error::ResponseError; | use meilisearch_types::error::{Code, ResponseError}; | ||||||
| use meilisearch_types::heed::RoTxn; | use meilisearch_types::heed::RoTxn; | ||||||
| use meilisearch_types::milli::index::ChatConfig; | use meilisearch_types::milli::index::ChatConfig; | ||||||
| use meilisearch_types::milli::prompt::{Prompt, PromptData}; | use meilisearch_types::milli::prompt::{Prompt, PromptData}; | ||||||
| @@ -237,7 +237,15 @@ pub fn format_documents<'doc>( | |||||||
|             Some(doc) => doc, |             Some(doc) => doc, | ||||||
|             None => unreachable!("Document with internal ID {docid} not found"), |             None => unreachable!("Document with internal ID {docid} not found"), | ||||||
|         }; |         }; | ||||||
|         let text = prompt.render_document(&external_docid, document, &gfid_map, doc_alloc).unwrap(); |         let text = match prompt.render_document(&external_docid, document, &gfid_map, doc_alloc) { | ||||||
|  |             Ok(text) => text, | ||||||
|  |             Err(err) => { | ||||||
|  |                 return Err(ResponseError::from_msg( | ||||||
|  |                     err.to_string(), | ||||||
|  |                     Code::InvalidChatSettingDocumentTemplate, | ||||||
|  |                 )) | ||||||
|  |             } | ||||||
|  |         }; | ||||||
|         renders.push(text); |         renders.push(text); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user