Skip to content

Commit c388b69

Browse files
committed
feat: add chat log step display
#324 #742
1 parent 07af6d0 commit c388b69

File tree

6 files changed

+96
-19
lines changed

6 files changed

+96
-19
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
"""063_update_chat_log_dll
2+
3+
Revision ID: c8751179a8de
4+
Revises: c9ab05247503
5+
Create Date: 2026-01-29 14:41:21.022781
6+
7+
"""
8+
from alembic import op
9+
import sqlalchemy as sa
10+
import sqlmodel.sql.sqltypes
11+
from sqlalchemy.dialects import postgresql
12+
13+
# revision identifiers, used by Alembic.
14+
revision = 'c8751179a8de'
15+
down_revision = 'c9ab05247503'
16+
branch_labels = None
17+
depends_on = None
18+
19+
20+
def upgrade():
21+
# ### commands auto generated by Alembic - please adjust! ###
22+
op.add_column('chat_log', sa.Column('error', sa.Boolean(), nullable=True))
23+
sql = '''
24+
UPDATE chat_log SET error = false
25+
'''
26+
op.execute(sql)
27+
op.alter_column('chat_log', 'error',
28+
existing_type=sa.BOOLEAN(),
29+
nullable=False)
30+
# ### end Alembic commands ###
31+
32+
33+
def downgrade():
34+
# ### commands auto generated by Alembic - please adjust! ###
35+
op.drop_column('chat_log', 'error')
36+
# ### end Alembic commands ###

backend/apps/chat/curd/chat.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,8 @@ def format_record(record: ChatRecordResult):
515515
return _dict
516516

517517

518-
def get_chat_log_history(session: SessionDep, chat_record_id: int, current_user: CurrentUser, without_steps: bool = False) -> ChatLogHistory:
518+
def get_chat_log_history(session: SessionDep, chat_record_id: int, current_user: CurrentUser,
519+
without_steps: bool = False) -> ChatLogHistory:
519520
"""
520521
获取ChatRecord的详细历史记录
521522
@@ -573,6 +574,7 @@ def get_chat_log_history(session: SessionDep, chat_record_id: int, current_user:
573574

574575
# 获取操作类型的枚举名称
575576
operate_name = None
577+
message = None
576578
if log.operate:
577579
# 如果是OperationEnum枚举实例
578580
if isinstance(log.operate, OperationEnum):
@@ -590,14 +592,24 @@ def get_chat_log_history(session: SessionDep, chat_record_id: int, current_user:
590592
else:
591593
operate_name = str(log.operate)
592594

595+
if log.messages is not None:
596+
message = log.messages
597+
if not log.operate == OperationEnum.CHOOSE_TABLE:
598+
try:
599+
message = orjson.loads(log.messages)
600+
except Exception:
601+
pass
602+
593603
# 创建ChatLogHistoryItem
594604
history_item = ChatLogHistoryItem(
595605
start_time=log.start_time,
596606
finish_time=log.finish_time,
597607
duration=duration,
598608
total_tokens=log_tokens,
599609
operate=operate_name,
600-
local_operation=log.local_operation
610+
local_operation=log.local_operation,
611+
error=log.error,
612+
message=message,
601613
)
602614

603615
steps.append(history_item)
@@ -622,6 +634,7 @@ def get_chat_log_history(session: SessionDep, chat_record_id: int, current_user:
622634

623635
return chat_log_history
624636

637+
625638
def get_chat_brief_generate(session: SessionDep, chat_id: int):
626639
chat = get_chat(session=session, chat_id=chat_id)
627640
if chat is not None and chat.brief_generate is not None:
@@ -1055,7 +1068,8 @@ def save_error_message(session: SessionDep, record_id: int, message: str) -> Cha
10551068

10561069
# log error finish
10571070
stmt = update(ChatLog).where(and_(ChatLog.pid == record.id, ChatLog.finish_time.is_(None))).values(
1058-
finish_time=record.finish_time
1071+
finish_time=record.finish_time,
1072+
error=True
10591073
)
10601074
session.execute(stmt)
10611075
session.commit()

backend/apps/chat/models/chat_model.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ class OperationEnum(Enum):
4747
EXECUTE_SQL = '12'
4848
GENERATE_PICTURE = '13'
4949

50+
5051
class ChatFinishStep(Enum):
5152
GENERATE_SQL = 1
5253
QUERY_DATA = 2
@@ -77,6 +78,7 @@ class ChatLog(SQLModel, table=True):
7778
finish_time: datetime = Field(sa_column=Column(DateTime(timezone=False), nullable=True))
7879
token_usage: Optional[dict | None | int] = Field(sa_column=Column(JSONB))
7980
local_operation: bool = Field(default=False)
81+
error: bool = Field(default=False)
8082

8183

8284
class Chat(SQLModel, table=True):
@@ -195,6 +197,9 @@ class ChatLogHistoryItem(BaseModel):
195197
total_tokens: Optional[int] = None # token总消耗
196198
operate: Optional[str] = None
197199
local_operation: Optional[bool] = False
200+
message: Optional[str | dict | list[dict]] = None
201+
error: Optional[bool] = False
202+
198203

199204
class ChatLogHistory(BaseModel):
200205
start_time: Optional[datetime] = None

backend/apps/chat/task/llm.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,6 @@ def init_messages(self, session: Session):
220220
self.sql_message.append(SystemMessage(
221221
content=self.chat_question.sql_sys_question(self.ds.type, self.enable_sql_row_limit)))
222222
if last_sql_messages is not None and len(last_sql_messages) > 0:
223-
# 获取最后3轮对话
224223
last_rounds = get_last_conversation_rounds(last_sql_messages, rounds=count_limit)
225224

226225
for _msg_dict in last_rounds:
@@ -234,20 +233,27 @@ def init_messages(self, session: Session):
234233

235234
last_chart_messages: List[dict[str, Any]] = self.generate_chart_logs[-1].messages if len(
236235
self.generate_chart_logs) > 0 else []
236+
if self.chat_question.regenerate_record_id:
237+
# filter record before regenerate_record_id
238+
_temp_log = next(
239+
filter(lambda obj: obj.pid == self.chat_question.regenerate_record_id, self.generate_chart_logs), None)
240+
last_chart_messages: List[dict[str, Any]] = _temp_log.messages if _temp_log else []
241+
242+
count_chart_limit = self.base_message_round_count_limit
237243

238244
self.chart_message = []
239245
# add sys prompt
240246
self.chart_message.append(SystemMessage(content=self.chat_question.chart_sys_question()))
241-
242247
if last_chart_messages is not None and len(last_chart_messages) > 0:
243-
# limit count
244-
for last_chart_message in last_chart_messages:
248+
last_rounds = get_last_conversation_rounds(last_chart_messages, rounds=count_chart_limit)
249+
250+
for _msg_dict in last_rounds:
245251
_msg: BaseMessage
246-
if last_chart_message.get('type') == 'human':
247-
_msg = HumanMessage(content=last_chart_message.get('content'))
252+
if _msg_dict.get('type') == 'human':
253+
_msg = HumanMessage(content=_msg_dict.get('content'))
248254
self.chart_message.append(_msg)
249-
elif last_chart_message.get('type') == 'ai':
250-
_msg = AIMessage(content=last_chart_message.get('content'))
255+
elif _msg_dict.get('type') == 'ai':
256+
_msg = AIMessage(content=_msg_dict.get('content'))
251257
self.chart_message.append(_msg)
252258

253259
def init_record(self, session: Session) -> ChatRecord:

frontend/src/api/chat.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,7 @@ export class ChatLogHistoryItem {
301301
total_tokens?: number | undefined
302302
operate?: string | undefined
303303
local_operation?: boolean | undefined
304+
error?: boolean | undefined
304305

305306
constructor()
306307
constructor(
@@ -309,22 +310,25 @@ export class ChatLogHistoryItem {
309310
duration: number | undefined,
310311
total_tokens: number | undefined,
311312
operate: string | undefined,
312-
local_operation: boolean | undefined
313+
local_operation: boolean | undefined,
314+
error: boolean | undefined
313315
)
314316
constructor(
315317
start_time?: Date | string,
316318
finish_time?: Date | string,
317319
duration?: number | undefined,
318320
total_tokens?: number | undefined,
319321
operate?: string | undefined,
320-
local_operation?: boolean | undefined
322+
local_operation?: boolean | undefined,
323+
error?: boolean | undefined
321324
) {
322325
this.start_time = getDate(start_time)
323326
this.finish_time = getDate(finish_time)
324327
this.duration = duration
325328
this.total_tokens = total_tokens
326329
this.operate = t('chat.log.' + operate)
327330
this.local_operation = !!local_operation
331+
this.error = !!error
328332
}
329333
}
330334

@@ -368,7 +372,8 @@ const toChatLogHistoryItem = (data?: any): any | undefined => {
368372
data.duration,
369373
data.total_tokens,
370374
data.operate,
371-
data.local_operation
375+
data.local_operation,
376+
data.error
372377
)
373378
}
374379

frontend/src/views/chat/ExecutionDetails.vue

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,22 @@ defineExpose({
5151
<div class="title">{{ t('parameter.execution_details') }}</div>
5252

5353
<div class="list">
54-
<div class="list-item" :key="ele.duration" v-for="ele in logHistory.steps">
55-
<div class="name">{{ ele.operate }}</div>
54+
<div v-for="ele in logHistory.steps" :key="ele.duration" class="list-item">
55+
<div class="name">
56+
{{ ele.operate }}
57+
</div>
5658
<div class="status">
59+
<div
60+
v-if="ele.total_tokens && ele.total_tokens > 0"
61+
class="time"
62+
style="margin-right: 12px"
63+
>
64+
{{ ele.total_tokens }} tokens
65+
</div>
5766
<div class="time">{{ ele.duration }}s</div>
5867
<el-icon size="16">
59-
<gou_icon v-if="true"></gou_icon>
60-
<icon_error v-else></icon_error>
68+
<icon_error v-if="ele.error"></icon_error>
69+
<gou_icon v-else></gou_icon>
6170
</el-icon>
6271
</div>
6372
</div>
@@ -94,7 +103,6 @@ defineExpose({
94103
.name {
95104
float: left;
96105
color: #646a73;
97-
font-family: PingFang SC;
98106
font-weight: 400;
99107
font-size: 14px;
100108
line-height: 22px;
@@ -132,6 +140,9 @@ defineExpose({
132140
font-weight: 500;
133141
font-size: 14px;
134142
line-height: 22px;
143+
display: flex;
144+
flex-direction: row;
145+
gap: 12px;
135146
}
136147
137148
.time {

0 commit comments

Comments
 (0)