3838from apps .system .schemas .system_schema import AssistantOutDsSchema
3939from common .core .config import settings
4040from common .core .deps import CurrentAssistant , CurrentUser
41+ from common .error import SingleMessageError
4142from common .utils .utils import SQLBotLogUtil , extract_nested_json , prepare_for_orjson
4243
4344warnings .filterwarnings ("ignore" )
@@ -78,7 +79,7 @@ def __init__(self, current_user: CurrentUser, chat_question: ChatQuestion,
7879 chat_id = chat_question .chat_id
7980 chat : Chat | None = self .session .get (Chat , chat_id )
8081 if not chat :
81- raise Exception (f"Chat with id { chat_id } not found" )
82+ raise SingleMessageError (f"Chat with id { chat_id } not found" )
8283 ds : CoreDatasource | AssistantOutDsSchema | None = None
8384 if chat .datasource :
8485 # Get available datasource
@@ -87,13 +88,13 @@ def __init__(self, current_user: CurrentUser, chat_question: ChatQuestion,
8788 self .out_ds_instance = AssistantOutDsFactory .get_instance (current_assistant )
8889 ds = self .out_ds_instance .get_ds (chat .datasource )
8990 if not ds :
90- raise Exception ("No available datasource configuration found" )
91+ raise SingleMessageError ("No available datasource configuration found" )
9192 chat_question .engine = ds .type
9293 chat_question .db_schema = self .out_ds_instance .get_db_schema (ds .id )
9394 else :
9495 ds = self .session .get (CoreDatasource , chat .datasource )
9596 if not ds :
96- raise Exception ("No available datasource configuration found" )
97+ raise SingleMessageError ("No available datasource configuration found" )
9798 chat_question .engine = ds .type_name if ds .type != 'excel' else 'PostgreSQL'
9899 chat_question .db_schema = get_table_schema (session = self .session , current_user = current_user , ds = ds )
99100
@@ -446,10 +447,11 @@ def select_datasource(self):
446447 _ds = self .session .get (CoreDatasource , _datasource )
447448 if not _ds :
448449 _datasource = None
449- raise Exception (f"Datasource configuration with id { _datasource } not found" )
450+ raise SingleMessageError (f"Datasource configuration with id { _datasource } not found" )
450451 self .ds = CoreDatasource (** _ds .model_dump ())
451452 self .chat_question .engine = _ds .type_name if _ds .type != 'excel' else 'PostgreSQL'
452- self .chat_question .db_schema = get_table_schema (session = self .session , current_user = self .current_user , ds = self .ds )
453+ self .chat_question .db_schema = get_table_schema (session = self .session ,
454+ current_user = self .current_user , ds = self .ds )
453455 _engine_type = self .chat_question .engine
454456 _chat .engine_type = _ds .type_name
455457 # save chat
@@ -459,9 +461,9 @@ def select_datasource(self):
459461 self .session .commit ()
460462
461463 elif data ['fail' ]:
462- raise Exception (data ['fail' ])
464+ raise SingleMessageError (data ['fail' ])
463465 else :
464- raise Exception ('No available datasource configuration found' )
466+ raise SingleMessageError ('No available datasource configuration found' )
465467
466468 except Exception as e :
467469 _error = e
@@ -542,7 +544,7 @@ def generate_with_sub_sql(self, sql, sub_mappings: list):
542544
543545 SQLBotLogUtil .info (full_dynamic_text )
544546 return full_dynamic_text
545-
547+
546548 def generate_assistant_dynamic_sql (self , sql , tables : List ):
547549 ds : AssistantOutDsSchema = self .ds
548550 sub_query = []
@@ -552,7 +554,7 @@ def generate_assistant_dynamic_sql(self, sql, tables: List):
552554 if not sub_query :
553555 return None
554556 return self .generate_with_sub_sql (sql = sql , sub_mappings = sub_query )
555-
557+
556558 def build_table_filter (self , sql : str , filters : list ):
557559 filter = json .dumps (filters , ensure_ascii = False )
558560 self .chat_question .sql = sql
@@ -672,23 +674,25 @@ def generate_chart(self):
672674 full_message = orjson .dumps (
673675 [{'type' : msg .type , 'content' : msg .content } for msg in
674676 self .chart_message ]).decode ())
677+
675678 def check_sql (self , res : str ) -> tuple [any ]:
676679 json_str = extract_nested_json (res )
677680 if json_str is None :
678- raise Exception ("Cannot parse sql from answer" )
681+ raise SingleMessageError (orjson .dumps ({'message' : 'Cannot parse sql from answer' ,
682+ 'traceback' : "Cannot parse sql from answer:\n " + res }).decode ())
679683 data : dict = orjson .loads (json_str )
680684 sql = ''
681685 message = ''
682686 if data ['success' ]:
683687 sql = data ['sql' ]
684688 else :
685689 message = data ['message' ]
686- raise Exception (message )
687-
690+ raise SingleMessageError (message )
691+
688692 if sql .strip () == '' :
689- raise Exception ("SQL query is empty" )
693+ raise SingleMessageError ("SQL query is empty" )
690694 return sql , data .get ('tables' )
691-
695+
692696 def check_save_sql (self , res : str ) -> str :
693697 sql , * _ = self .check_sql (res = res )
694698 save_sql (session = self .session , sql = sql , record_id = self .record .id )
@@ -701,7 +705,8 @@ def check_save_chart(self, res: str) -> Dict[str, Any]:
701705
702706 json_str = extract_nested_json (res )
703707 if json_str is None :
704- raise Exception ("Cannot parse chart config from answer" )
708+ raise SingleMessageError (orjson .dumps ({'message' : 'Cannot parse chart config from answer' ,
709+ 'traceback' : "Cannot parse chart config from answer:\n " + res }).decode ())
705710 data = orjson .loads (json_str )
706711
707712 chart : Dict [str , Any ] = {}
@@ -729,7 +734,7 @@ def check_save_chart(self, res: str) -> Dict[str, Any]:
729734 error = True
730735
731736 if error :
732- raise Exception (message )
737+ raise SingleMessageError (message )
733738
734739 save_chart (session = self .session , chart = orjson .dumps (chart ).decode (), record_id = self .record .id )
735740
@@ -865,7 +870,7 @@ def run_task(self, in_chat: bool = True):
865870 if dynamic_sql_result :
866871 SQLBotLogUtil .info (dynamic_sql_result )
867872 sql , * _ = self .check_sql (res = dynamic_sql_result )
868-
873+
869874 sql_result = self .generate_assistant_filter (sql , tables )
870875 else :
871876 sql_result = self .generate_filter (sql , tables ) # maybe no sql and tables
@@ -951,12 +956,16 @@ def run_task(self, in_chat: bool = True):
951956 SQLBotLogUtil .info (image_url )
952957 yield f'![{ chart ["type" ]} ]({ image_url } )'
953958 except Exception as e :
954- traceback .print_exc ()
955- self .save_error (message = str (e ))
959+ error_msg : str
960+ if isinstance (e , SingleMessageError ):
961+ error_msg = str (e )
962+ else :
963+ error_msg = orjson .dumps ({'message' : str (e ), 'traceback' : traceback .format_exc (limit = 1 )}).decode ()
964+ self .save_error (message = error_msg )
956965 if in_chat :
957- yield orjson .dumps ({'content' : str ( e ) , 'type' : 'error' }).decode () + '\n \n '
966+ yield orjson .dumps ({'content' : error_msg , 'type' : 'error' }).decode () + '\n \n '
958967 else :
959- yield f'> ❌ **ERROR**\n \n > \n \n > { str ( e ) } 。'
968+ yield f'> ❌ **ERROR**\n \n > \n \n > { error_msg } 。'
960969
961970 def run_recommend_questions_task_async (self ):
962971 self .future = executor .submit (self .run_recommend_questions_task_cache )
@@ -1022,31 +1031,37 @@ def run_analysis_or_predict_task(self, action_type: str):
10221031
10231032 self .finish ()
10241033 except Exception as e :
1025- traceback .print_exc ()
1026- self .save_error (message = str (e ))
1027- yield orjson .dumps ({'content' : str (e ), 'type' : 'error' }).decode () + '\n \n '
1034+ error_msg : str
1035+ if isinstance (e , SingleMessageError ):
1036+ error_msg = str (e )
1037+ else :
1038+ error_msg = orjson .dumps ({'message' : str (e ), 'traceback' : traceback .format_exc (limit = 1 )}).decode ()
1039+ self .save_error (message = error_msg )
1040+ yield orjson .dumps ({'content' : error_msg , 'type' : 'error' }).decode () + '\n \n '
10281041 finally :
10291042 # end
10301043 pass
1031-
1044+
10321045 def validate_history_ds (self ):
10331046 _ds = self .ds
10341047 if not self .current_assistant :
1035- current_ds = self .session .get (CoreDatasource , _ds .id )
1036- if not current_ds :
1037- raise Exception ('ds is invalid' )
1048+ try :
1049+ current_ds = self .session .get (CoreDatasource , _ds .id )
1050+ if not current_ds :
1051+ raise SingleMessageError ('chat.ds_is_invalid' )
1052+ except Exception as e :
1053+ raise SingleMessageError ("chat.ds_is_invalid" )
10381054 else :
10391055 try :
10401056 _ds_list : list [dict ] = get_assistant_ds (session = self .session , llm_service = self )
10411057 match_ds = any (item .get ("id" ) == _ds .id for item in _ds_list )
10421058 if not match_ds :
10431059 type = self .current_assistant .type
10441060 msg = f"ds is invalid [please check ds list and public ds list]" if type == 0 else f"ds is invalid [please check ds api]"
1045- raise Exception (msg )
1061+ raise SingleMessageError (msg )
10461062 except Exception as e :
1047- raise Exception (f"ds is invalid [{ str (e )} ]" )
1048-
1049-
1063+ raise SingleMessageError (f"ds is invalid [{ str (e )} ]" )
1064+
10501065
10511066def execute_sql_with_db (db : SQLDatabase , sql : str ) -> str :
10521067 """Execute SQL query using SQLDatabase
0 commit comments