Skip to content

Commit 87241b6

Browse files
committed
feat: modify generate chat
1 parent d03e8fc commit 87241b6

File tree

3 files changed

+194
-185
lines changed

3 files changed

+194
-185
lines changed

backend/apps/chat/api/chat.py

Lines changed: 15 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,14 @@
11
import traceback
2-
from typing import List
32

43
import orjson
54
from fastapi import APIRouter, HTTPException
65
from fastapi.responses import StreamingResponse
7-
from sqlmodel import select
86

97
from apps.chat.curd.chat import list_chats, get_chat_with_records, create_chat, rename_chat, \
10-
delete_chat, list_records
11-
from apps.chat.models.chat_model import CreateChat, ChatRecord, RenameChat, Chat, ChatQuestion, ChatMcp
12-
from apps.chat.task.llm import LLMService
13-
from apps.datasource.crud.datasource import get_table_schema
14-
from apps.datasource.models.datasource import CoreDatasource
15-
from apps.system.crud.user import get_user_info
16-
from apps.system.models.system_model import AiModelDetail
17-
from common.core.deps import SessionDep, CurrentUser, get_current_user
8+
delete_chat
9+
from apps.chat.models.chat_model import CreateChat, ChatRecord, RenameChat, ChatQuestion
10+
from apps.chat.task.llm import LLMService, run_task
11+
from common.core.deps import SessionDep, CurrentUser
1812

1913
router = APIRouter(tags=["Data Q&A"], prefix="/chat")
2014

@@ -81,107 +75,17 @@ async def stream_sql(session: SessionDep, current_user: CurrentUser, request_que
8175
Streaming response with analysis results
8276
"""
8377

84-
chat = session.query(Chat).filter(Chat.id == request_question.chat_id).first()
85-
if not chat:
86-
raise HTTPException(
87-
status_code=400,
88-
detail=f"Chat with id {request_question.chat_id} not found"
89-
)
90-
ds: CoreDatasource | None = None
91-
if chat.datasource:
92-
# Get available datasource
93-
ds = session.query(CoreDatasource).filter(CoreDatasource.id == chat.datasource).first()
94-
if not ds:
95-
raise HTTPException(
96-
status_code=500,
97-
detail="No available datasource configuration found"
98-
)
99-
100-
request_question.engine = ds.type_name if ds.type != 'excel' else 'PostgreSQL'
101-
102-
# Get available AI model
103-
aimodel = session.exec(select(AiModelDetail).where(
104-
AiModelDetail.status == True,
105-
AiModelDetail.api_key.is_not(None)
106-
)).first()
107-
if not aimodel:
78+
try:
79+
llm_service = LLMService(session, current_user, request_question)
80+
llm_service.init_record()
81+
except Exception as e:
82+
traceback.print_exc()
10883
raise HTTPException(
10984
status_code=500,
110-
detail="No available AI model configuration found"
85+
detail=str(e)
11186
)
11287

113-
history_records: List[ChatRecord] = list(filter(lambda r: True if r.first_chat != True else False,
114-
list_records(session=session, current_user=current_user,
115-
chart_id=request_question.chat_id)))
116-
# get schema
117-
if ds:
118-
request_question.db_schema = get_table_schema(session=session, ds=ds)
119-
120-
db_user = get_user_info(session=session, user_id=current_user.id)
121-
request_question.lang = db_user.language
122-
123-
llm_service = LLMService(request_question, aimodel, history_records,
124-
CoreDatasource(**ds.model_dump()) if ds else None)
125-
126-
llm_service.init_record(session=session, current_user=current_user)
127-
128-
def run_task():
129-
try:
130-
# return id
131-
yield orjson.dumps({'type': 'id', 'id': llm_service.get_record().id}).decode() + '\n\n'
132-
133-
# select datasource if datasource is none
134-
if not ds:
135-
ds_res = llm_service.select_datasource(session=session)
136-
for chunk in ds_res:
137-
yield orjson.dumps({'content': chunk, 'type': 'datasource-result'}).decode() + '\n\n'
138-
yield orjson.dumps({'id': llm_service.ds.id, 'datasource_name': llm_service.ds.name,
139-
'engine_type': llm_service.ds.type_name, 'type': 'datasource'}).decode() + '\n\n'
140-
141-
llm_service.chat_question.db_schema = get_table_schema(session=session, ds=llm_service.ds)
142-
143-
# generate sql
144-
sql_res = llm_service.generate_sql(session=session)
145-
full_sql_text = ''
146-
for chunk in sql_res:
147-
full_sql_text += chunk
148-
yield orjson.dumps({'content': chunk, 'type': 'sql-result'}).decode() + '\n\n'
149-
yield orjson.dumps({'type': 'info', 'msg': 'sql generated'}).decode() + '\n\n'
150-
151-
# filter sql
152-
print(full_sql_text)
153-
sql = llm_service.check_save_sql(session=session, res=full_sql_text)
154-
print(sql)
155-
yield orjson.dumps({'content': sql, 'type': 'sql'}).decode() + '\n\n'
156-
157-
# execute sql
158-
result = llm_service.execute_sql(sql=sql)
159-
llm_service.save_sql_data(session=session, data_obj=result)
160-
yield orjson.dumps({'content': orjson.dumps(result).decode(), 'type': 'sql-data'}).decode() + '\n\n'
161-
162-
# generate chart
163-
chart_res = llm_service.generate_chart(session=session)
164-
full_chart_text = ''
165-
for chunk in chart_res:
166-
full_chart_text += chunk
167-
yield orjson.dumps({'content': chunk, 'type': 'chart-result'}).decode() + '\n\n'
168-
yield orjson.dumps({'type': 'info', 'msg': 'chart generated'}).decode() + '\n\n'
169-
170-
# filter chart
171-
print(full_chart_text)
172-
chart = llm_service.check_save_chart(session=session, res=full_chart_text)
173-
print(chart)
174-
yield orjson.dumps({'content': orjson.dumps(chart).decode(), 'type': 'chart'}).decode() + '\n\n'
175-
176-
llm_service.finish(session=session)
177-
yield orjson.dumps({'type': 'finish'}).decode() + '\n\n'
178-
179-
except Exception as e:
180-
traceback.print_exc()
181-
llm_service.save_error(session=session, message=str(e))
182-
yield orjson.dumps({'content': str(e), 'type': 'error'}).decode() + '\n\n'
183-
184-
return StreamingResponse(run_task(), media_type="text/event-stream")
88+
return StreamingResponse(run_task(llm_service, session), media_type="text/event-stream")
18589

18690

18791
@router.post("/record/{chart_record_id}/{action_type}")
@@ -205,35 +109,9 @@ async def analysis_or_predict(session: SessionDep, current_user: CurrentUser, ch
205109
detail=f"Chat record with id {chart_record_id} has not generated chart, do not support to analyze it"
206110
)
207111

208-
chat = session.query(Chat).filter(Chat.id == record.chat_id).first()
209-
if not chat:
210-
raise HTTPException(
211-
status_code=400,
212-
detail=f"Chat with id {record.chart_id} not found"
213-
)
214-
215-
if chat.create_by != current_user.id:
216-
raise HTTPException(
217-
status_code=401,
218-
detail=f"You cannot use the chat with id {record.chart_id}"
219-
)
220-
221-
# Get available AI model
222-
aimodel = session.exec(select(AiModelDetail).where(
223-
AiModelDetail.status == True,
224-
AiModelDetail.api_key.is_not(None)
225-
)).first()
226-
if not aimodel:
227-
raise HTTPException(
228-
status_code=500,
229-
detail="No available AI model configuration found"
230-
)
231-
232-
request_question = ChatQuestion(chat_id=chat.id, question='')
233-
db_user = get_user_info(session=session, user_id=current_user.id)
234-
request_question.lang = db_user.language
112+
request_question = ChatQuestion(chat_id=record.chat_id, question='')
235113

236-
llm_service = LLMService(request_question, aimodel)
114+
llm_service = LLMService(session, current_user, request_question)
237115
llm_service.set_record(record)
238116

239117
def run_task():
@@ -249,14 +127,14 @@ def run_task():
249127

250128
elif action_type == 'predict':
251129
# generate predict
252-
analysis_res = llm_service.generate_predict(session=session)
130+
analysis_res = llm_service.generate_predict()
253131
full_text = ''
254132
for chunk in analysis_res:
255133
yield orjson.dumps({'content': chunk, 'type': 'predict-result'}).decode() + '\n\n'
256134
full_text += chunk
257135
yield orjson.dumps({'type': 'info', 'msg': 'predict generated'}).decode() + '\n\n'
258136

259-
_data = llm_service.check_save_predict_data(session=session, res=full_text)
137+
_data = llm_service.check_save_predict_data(res=full_text)
260138
yield orjson.dumps({'type': 'predict', 'content': _data}).decode() + '\n\n'
261139

262140
yield orjson.dumps({'type': 'predict_finish'}).decode() + '\n\n'

0 commit comments

Comments
 (0)