diff --git a/README.md b/README.md index 8bf9995b..29e2a6ed 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,8 @@ docker compose up -d 如你有更多问题,可以加入我们的技术交流群与我们交流。 -TBD: 交流群二维码 +contact_me_qr + ## UI 展示 diff --git a/backend/apps/chat/curd/chat.py b/backend/apps/chat/curd/chat.py index 3f10f678..6369536d 100644 --- a/backend/apps/chat/curd/chat.py +++ b/backend/apps/chat/curd/chat.py @@ -1,10 +1,9 @@ import datetime -import sqlparse from typing import List import orjson -from sqlalchemy import and_ -from sqlalchemy.orm import load_only +import sqlparse +from sqlalchemy import and_, select from apps.chat.models.chat_model import Chat, ChatRecord, CreateChat, ChatInfo, RenameChat, ChatQuestion from apps.datasource.models.datasource import CoreDatasource @@ -47,26 +46,29 @@ def delete_chat(session, chart_id) -> str: def get_chat_chart_data(session: SessionDep, chart_record_id: int): - res = session.query(ChatRecord).options(load_only(ChatRecord.data)).get(chart_record_id) - if res: + stmt = select(ChatRecord.data).where(and_(ChatRecord.id == chart_record_id)) + res = session.execute(stmt) + for row in res: try: - return orjson.loads(res.data) + return orjson.loads(row.data) except Exception: pass return {} def get_chat_predict_data(session: SessionDep, chart_record_id: int): - res = session.query(ChatRecord).options(load_only(ChatRecord.predict_data)).get(chart_record_id) - if res: + stmt = select(ChatRecord.predict_data).where(and_(ChatRecord.id == chart_record_id)) + res = session.execute(stmt) + for row in res: try: - return orjson.loads(res.predict_data) + return orjson.loads(row.predict_data) except Exception: pass - return '' + return {} -def get_chat_with_records(session: SessionDep, chart_id: int, current_user: CurrentUser, current_assistant: CurrentAssistant) -> ChatInfo: +def get_chat_with_records(session: SessionDep, chart_id: int, current_user: CurrentUser, + current_assistant: CurrentAssistant) -> ChatInfo: chat = session.get(Chat, chart_id) if not chat: raise Exception(f"Chat with id {chart_id} not found") @@ -78,7 +80,7 @@ def get_chat_with_records(session: SessionDep, chart_id: int, current_user: Curr ds = out_ds_instance.get_ds(chat.datasource) else: ds = session.get(CoreDatasource, chat.datasource) if chat.datasource else None - + if not ds: chat_info.datasource_exists = False chat_info.datasource_name = 'Datasource not exist' @@ -87,14 +89,25 @@ def get_chat_with_records(session: SessionDep, chart_id: int, current_user: Curr chat_info.datasource_name = ds.name chat_info.ds_type = ds.type - record_list = session.query(ChatRecord).options( - load_only(ChatRecord.id, ChatRecord.chat_id, ChatRecord.create_time, ChatRecord.finish_time, - ChatRecord.question, ChatRecord.sql_answer, ChatRecord.sql, ChatRecord.data, + stmt = select(ChatRecord.id, ChatRecord.chat_id, ChatRecord.create_time, ChatRecord.finish_time, + ChatRecord.question, ChatRecord.sql_answer, ChatRecord.sql, ChatRecord.chart_answer, ChatRecord.chart, ChatRecord.analysis, ChatRecord.predict, ChatRecord.datasource_select_answer, ChatRecord.analysis_record_id, ChatRecord.predict_record_id, ChatRecord.recommended_question, ChatRecord.first_chat, - ChatRecord.predict_data, ChatRecord.finish, ChatRecord.error)).filter( - and_(Chat.create_by == current_user.id, ChatRecord.chat_id == chart_id)).order_by(ChatRecord.create_time).all() + ChatRecord.finish, ChatRecord.error).where( + and_(ChatRecord.create_by == current_user.id, ChatRecord.chat_id == chart_id)).order_by(ChatRecord.create_time) + result = session.execute(stmt).all() + record_list: list[ChatRecord] = [] + for row in result: + record_list.append( + ChatRecord(id=row.id, chat_id=row.chat_id, create_time=row.create_time, finish_time=row.finish_time, + question=row.question, sql_answer=row.sql_answer, sql=row.sql, + chart_answer=row.chart_answer, chart=row.chart, + analysis=row.analysis, predict=row.predict, + datasource_select_answer=row.datasource_select_answer, + analysis_record_id=row.analysis_record_id, predict_record_id=row.predict_record_id, + recommended_question=row.recommended_question, first_chat=row.first_chat, + finish=row.finish, error=row.error)) result = list(map(format_record, record_list)) diff --git a/backend/apps/chat/task/llm.py b/backend/apps/chat/task/llm.py index d65688b9..34640ff4 100644 --- a/backend/apps/chat/task/llm.py +++ b/backend/apps/chat/task/llm.py @@ -655,14 +655,21 @@ class LLMService: if json_str is None: raise SingleMessageError(orjson.dumps({'message': 'Cannot parse sql from answer', 'traceback': "Cannot parse sql from answer:\n" + res}).decode()) - data: dict = orjson.loads(json_str) - sql = '' - message = '' - if data['success']: - sql = data['sql'] - else: - message = data['message'] - raise SingleMessageError(message) + sql: str + data: dict + try: + data = orjson.loads(json_str) + + if data['success']: + sql = data['sql'] + else: + message = data['message'] + raise SingleMessageError(message) + except SingleMessageError as e: + raise e + except Exception: + raise SingleMessageError(orjson.dumps({'message': 'Cannot parse sql from answer', + 'traceback': "Cannot parse sql from answer:\n" + res}).decode()) if sql.strip() == '': raise SingleMessageError("SQL query is empty") @@ -682,31 +689,36 @@ class LLMService: if json_str is None: raise SingleMessageError(orjson.dumps({'message': 'Cannot parse chart config from answer', 'traceback': "Cannot parse chart config from answer:\n" + res}).decode()) - data = orjson.loads(json_str) + data: dict chart: Dict[str, Any] = {} message = '' error = False - if data['type'] and data['type'] != 'error': - # todo type check - chart = data - if chart.get('columns'): - for v in chart.get('columns'): - v['value'] = v.get('value').lower() - if chart.get('axis'): - if chart.get('axis').get('x'): - chart.get('axis').get('x')['value'] = chart.get('axis').get('x').get('value').lower() - if chart.get('axis').get('y'): - chart.get('axis').get('y')['value'] = chart.get('axis').get('y').get('value').lower() - if chart.get('axis').get('series'): - chart.get('axis').get('series')['value'] = chart.get('axis').get('series').get('value').lower() - elif data['type'] == 'error': - message = data['reason'] - error = True - else: - message = 'Chart is empty' + try: + data = orjson.loads(json_str) + if data['type'] and data['type'] != 'error': + # todo type check + chart = data + if chart.get('columns'): + for v in chart.get('columns'): + v['value'] = v.get('value').lower() + if chart.get('axis'): + if chart.get('axis').get('x'): + chart.get('axis').get('x')['value'] = chart.get('axis').get('x').get('value').lower() + if chart.get('axis').get('y'): + chart.get('axis').get('y')['value'] = chart.get('axis').get('y').get('value').lower() + if chart.get('axis').get('series'): + chart.get('axis').get('series')['value'] = chart.get('axis').get('series').get('value').lower() + elif data['type'] == 'error': + message = data['reason'] + error = True + else: + raise Exception('Chart is empty') + except Exception: error = True + message = orjson.dumps({'message': 'Cannot parse chart config from answer', + 'traceback': "Cannot parse chart config from answer:\n" + res}).decode() if error: raise SingleMessageError(message) diff --git a/frontend/src/entity/supplier.ts b/frontend/src/entity/supplier.ts index 9a60551c..5c5eebe9 100644 --- a/frontend/src/entity/supplier.ts +++ b/frontend/src/entity/supplier.ts @@ -45,8 +45,8 @@ export const supplierList: Array<{ { name: 'qwen-long' }, { name: 'qwen-long-latest' }, { name: 'qwen-omni-turbo' }, - { name: 'qwen-omni-turbo-realtime' }, - { name: 'qwen-omni-turbo-realtime-latest' }, + /* { name: 'qwen-omni-turbo-realtime' }, + { name: 'qwen-omni-turbo-realtime-latest' }, */ { name: 'qvq-max' }, { name: 'qvq-max-latest' }, { name: 'qvq-plus' }, diff --git a/frontend/src/views/chat/ChatCreator.vue b/frontend/src/views/chat/ChatCreator.vue index f53ea62e..02769f97 100644 --- a/frontend/src/views/chat/ChatCreator.vue +++ b/frontend/src/views/chat/ChatCreator.vue @@ -51,6 +51,7 @@ function listDs() { const innerDs = ref() const loading = ref(false) +const statusLoading = ref(false) function showDs() { listDs() @@ -68,12 +69,18 @@ function selectDsInDialog(ds: any) { function confirmSelectDs() { if (innerDs.value) { + statusLoading.value = true //check first - datasourceApi.check_by_id(innerDs.value).then((res: any) => { - if (res) { - createChat(innerDs.value) - } - }) + datasourceApi + .check_by_id(innerDs.value) + .then((res: any) => { + if (res) { + createChat(innerDs.value) + } + }) + .finally(() => { + statusLoading.value = false + }) } } @@ -117,98 +124,100 @@ defineExpose({