mirror of
https://gh-proxy.org/https://github.com/klinsmaya/SQLBot.git
synced 2026-11-08 01:06:59 +08:00
@@ -0,0 +1,36 @@
|
||||
"""063_update_chat_log_dll
|
||||
|
||||
Revision ID: c8751179a8de
|
||||
Revises: c9ab05247503
|
||||
Create Date: 2026-01-29 14:41:21.022781
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
import sqlmodel.sql.sqltypes
|
||||
from sqlalchemy.dialects import postgresql
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'c8751179a8de'
|
||||
down_revision = 'c9ab05247503'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.add_column('chat_log', sa.Column('error', sa.Boolean(), nullable=True))
|
||||
sql = '''
|
||||
UPDATE chat_log SET error = false
|
||||
'''
|
||||
op.execute(sql)
|
||||
op.alter_column('chat_log', 'error',
|
||||
existing_type=sa.BOOLEAN(),
|
||||
nullable=False)
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_column('chat_log', 'error')
|
||||
# ### end Alembic commands ###
|
||||
@@ -515,7 +515,8 @@ def format_record(record: ChatRecordResult):
|
||||
return _dict
|
||||
|
||||
|
||||
def get_chat_log_history(session: SessionDep, chat_record_id: int, current_user: CurrentUser, without_steps: bool = False) -> ChatLogHistory:
|
||||
def get_chat_log_history(session: SessionDep, chat_record_id: int, current_user: CurrentUser,
|
||||
without_steps: bool = False) -> ChatLogHistory:
|
||||
"""
|
||||
获取ChatRecord的详细历史记录
|
||||
|
||||
@@ -573,6 +574,7 @@ def get_chat_log_history(session: SessionDep, chat_record_id: int, current_user:
|
||||
|
||||
# 获取操作类型的枚举名称
|
||||
operate_name = None
|
||||
message = None
|
||||
if log.operate:
|
||||
# 如果是OperationEnum枚举实例
|
||||
if isinstance(log.operate, OperationEnum):
|
||||
@@ -590,6 +592,14 @@ def get_chat_log_history(session: SessionDep, chat_record_id: int, current_user:
|
||||
else:
|
||||
operate_name = str(log.operate)
|
||||
|
||||
if log.messages is not None:
|
||||
message = log.messages
|
||||
if not log.operate == OperationEnum.CHOOSE_TABLE:
|
||||
try:
|
||||
message = orjson.loads(log.messages)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# 创建ChatLogHistoryItem
|
||||
history_item = ChatLogHistoryItem(
|
||||
start_time=log.start_time,
|
||||
@@ -597,7 +607,9 @@ def get_chat_log_history(session: SessionDep, chat_record_id: int, current_user:
|
||||
duration=duration,
|
||||
total_tokens=log_tokens,
|
||||
operate=operate_name,
|
||||
local_operation=log.local_operation
|
||||
local_operation=log.local_operation,
|
||||
error=log.error,
|
||||
message=message,
|
||||
)
|
||||
|
||||
steps.append(history_item)
|
||||
@@ -622,6 +634,7 @@ def get_chat_log_history(session: SessionDep, chat_record_id: int, current_user:
|
||||
|
||||
return chat_log_history
|
||||
|
||||
|
||||
def get_chat_brief_generate(session: SessionDep, chat_id: int):
|
||||
chat = get_chat(session=session, chat_id=chat_id)
|
||||
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
|
||||
|
||||
# log error finish
|
||||
stmt = update(ChatLog).where(and_(ChatLog.pid == record.id, ChatLog.finish_time.is_(None))).values(
|
||||
finish_time=record.finish_time
|
||||
finish_time=record.finish_time,
|
||||
error=True
|
||||
)
|
||||
session.execute(stmt)
|
||||
session.commit()
|
||||
|
||||
@@ -47,6 +47,7 @@ class OperationEnum(Enum):
|
||||
EXECUTE_SQL = '12'
|
||||
GENERATE_PICTURE = '13'
|
||||
|
||||
|
||||
class ChatFinishStep(Enum):
|
||||
GENERATE_SQL = 1
|
||||
QUERY_DATA = 2
|
||||
@@ -77,6 +78,7 @@ class ChatLog(SQLModel, table=True):
|
||||
finish_time: datetime = Field(sa_column=Column(DateTime(timezone=False), nullable=True))
|
||||
token_usage: Optional[dict | None | int] = Field(sa_column=Column(JSONB))
|
||||
local_operation: bool = Field(default=False)
|
||||
error: bool = Field(default=False)
|
||||
|
||||
|
||||
class Chat(SQLModel, table=True):
|
||||
@@ -195,6 +197,9 @@ class ChatLogHistoryItem(BaseModel):
|
||||
total_tokens: Optional[int] = None # token总消耗
|
||||
operate: Optional[str] = None
|
||||
local_operation: Optional[bool] = False
|
||||
message: Optional[str | dict | list[dict]] = None
|
||||
error: Optional[bool] = False
|
||||
|
||||
|
||||
class ChatLogHistory(BaseModel):
|
||||
start_time: Optional[datetime] = None
|
||||
|
||||
@@ -220,7 +220,6 @@ class LLMService:
|
||||
self.sql_message.append(SystemMessage(
|
||||
content=self.chat_question.sql_sys_question(self.ds.type, self.enable_sql_row_limit)))
|
||||
if last_sql_messages is not None and len(last_sql_messages) > 0:
|
||||
# 获取最后3轮对话
|
||||
last_rounds = get_last_conversation_rounds(last_sql_messages, rounds=count_limit)
|
||||
|
||||
for _msg_dict in last_rounds:
|
||||
@@ -234,20 +233,27 @@ class LLMService:
|
||||
|
||||
last_chart_messages: List[dict[str, Any]] = self.generate_chart_logs[-1].messages if len(
|
||||
self.generate_chart_logs) > 0 else []
|
||||
if self.chat_question.regenerate_record_id:
|
||||
# filter record before regenerate_record_id
|
||||
_temp_log = next(
|
||||
filter(lambda obj: obj.pid == self.chat_question.regenerate_record_id, self.generate_chart_logs), None)
|
||||
last_chart_messages: List[dict[str, Any]] = _temp_log.messages if _temp_log else []
|
||||
|
||||
count_chart_limit = self.base_message_round_count_limit
|
||||
|
||||
self.chart_message = []
|
||||
# add sys prompt
|
||||
self.chart_message.append(SystemMessage(content=self.chat_question.chart_sys_question()))
|
||||
|
||||
if last_chart_messages is not None and len(last_chart_messages) > 0:
|
||||
# limit count
|
||||
for last_chart_message in last_chart_messages:
|
||||
last_rounds = get_last_conversation_rounds(last_chart_messages, rounds=count_chart_limit)
|
||||
|
||||
for _msg_dict in last_rounds:
|
||||
_msg: BaseMessage
|
||||
if last_chart_message.get('type') == 'human':
|
||||
_msg = HumanMessage(content=last_chart_message.get('content'))
|
||||
if _msg_dict.get('type') == 'human':
|
||||
_msg = HumanMessage(content=_msg_dict.get('content'))
|
||||
self.chart_message.append(_msg)
|
||||
elif last_chart_message.get('type') == 'ai':
|
||||
_msg = AIMessage(content=last_chart_message.get('content'))
|
||||
elif _msg_dict.get('type') == 'ai':
|
||||
_msg = AIMessage(content=_msg_dict.get('content'))
|
||||
self.chart_message.append(_msg)
|
||||
|
||||
def init_record(self, session: Session) -> ChatRecord:
|
||||
|
||||
@@ -301,6 +301,7 @@ export class ChatLogHistoryItem {
|
||||
total_tokens?: number | undefined
|
||||
operate?: string | undefined
|
||||
local_operation?: boolean | undefined
|
||||
error?: boolean | undefined
|
||||
|
||||
constructor()
|
||||
constructor(
|
||||
@@ -309,7 +310,8 @@ export class ChatLogHistoryItem {
|
||||
duration: number | undefined,
|
||||
total_tokens: number | undefined,
|
||||
operate: string | undefined,
|
||||
local_operation: boolean | undefined
|
||||
local_operation: boolean | undefined,
|
||||
error: boolean | undefined
|
||||
)
|
||||
constructor(
|
||||
start_time?: Date | string,
|
||||
@@ -317,7 +319,8 @@ export class ChatLogHistoryItem {
|
||||
duration?: number | undefined,
|
||||
total_tokens?: number | undefined,
|
||||
operate?: string | undefined,
|
||||
local_operation?: boolean | undefined
|
||||
local_operation?: boolean | undefined,
|
||||
error?: boolean | undefined
|
||||
) {
|
||||
this.start_time = getDate(start_time)
|
||||
this.finish_time = getDate(finish_time)
|
||||
@@ -325,6 +328,7 @@ export class ChatLogHistoryItem {
|
||||
this.total_tokens = total_tokens
|
||||
this.operate = t('chat.log.' + operate)
|
||||
this.local_operation = !!local_operation
|
||||
this.error = !!error
|
||||
}
|
||||
}
|
||||
|
||||
@@ -368,7 +372,8 @@ const toChatLogHistoryItem = (data?: any): any | undefined => {
|
||||
data.duration,
|
||||
data.total_tokens,
|
||||
data.operate,
|
||||
data.local_operation
|
||||
data.local_operation,
|
||||
data.error
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -51,13 +51,22 @@ defineExpose({
|
||||
<div class="title">{{ t('parameter.execution_details') }}</div>
|
||||
|
||||
<div class="list">
|
||||
<div class="list-item" :key="ele.duration" v-for="ele in logHistory.steps">
|
||||
<div class="name">{{ ele.operate }}</div>
|
||||
<div v-for="ele in logHistory.steps" :key="ele.duration" class="list-item">
|
||||
<div class="name">
|
||||
{{ ele.operate }}
|
||||
</div>
|
||||
<div class="status">
|
||||
<div
|
||||
v-if="ele.total_tokens && ele.total_tokens > 0"
|
||||
class="time"
|
||||
style="margin-right: 12px"
|
||||
>
|
||||
{{ ele.total_tokens }} tokens
|
||||
</div>
|
||||
<div class="time">{{ ele.duration }}s</div>
|
||||
<el-icon size="16">
|
||||
<gou_icon v-if="true"></gou_icon>
|
||||
<icon_error v-else></icon_error>
|
||||
<icon_error v-if="ele.error"></icon_error>
|
||||
<gou_icon v-else></gou_icon>
|
||||
</el-icon>
|
||||
</div>
|
||||
</div>
|
||||
@@ -94,7 +103,6 @@ defineExpose({
|
||||
.name {
|
||||
float: left;
|
||||
color: #646a73;
|
||||
font-family: PingFang SC;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
@@ -132,6 +140,9 @@ defineExpose({
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.time {
|
||||
|
||||
Reference in New Issue
Block a user