From bb5c04674e6d10be5e477d80c974c67bc1e1b6fd Mon Sep 17 00:00:00 2001 From: fit2cloud-chenyw Date: Mon, 14 Jul 2025 16:13:25 +0800 Subject: [PATCH] perf: Assistant chat history --- backend/apps/chat/curd/chat.py | 4 ++-- backend/apps/system/api/assistant.py | 7 ++++--- backend/apps/system/crud/assistant.py | 6 +++++- backend/apps/system/middleware/auth.py | 7 ++++--- backend/common/core/deps.py | 6 ++++++ frontend/src/stores/assistant.ts | 17 +++++++++++++++++ frontend/src/utils/request.ts | 2 +- frontend/src/views/embedded/assistant.vue | 5 ++++- 8 files changed, 43 insertions(+), 11 deletions(-) diff --git a/backend/apps/chat/curd/chat.py b/backend/apps/chat/curd/chat.py index 0da2fabe..70129f07 100644 --- a/backend/apps/chat/curd/chat.py +++ b/backend/apps/chat/curd/chat.py @@ -4,6 +4,7 @@ from typing import List import orjson from sqlalchemy import and_ from sqlalchemy.orm import load_only +from sqlmodel import select from apps.chat.models.chat_model import Chat, ChatRecord, CreateChat, ChatInfo, RenameChat, ChatQuestion from apps.datasource.models.datasource import CoreDatasource @@ -12,8 +13,7 @@ from common.utils.utils import extract_nested_json def list_chats(session: SessionDep, current_user: CurrentUser) -> List[Chat]: - chart_list = session.query(Chat).filter(Chat.create_by == current_user.id).order_by( - Chat.create_time.desc()).all() + chart_list = session.exec(select(Chat).where(Chat.create_by == current_user.id).order_by(Chat.create_time.desc())).all() return chart_list diff --git a/backend/apps/system/api/assistant.py b/backend/apps/system/api/assistant.py index b9657e21..836461ee 100644 --- a/backend/apps/system/api/assistant.py +++ b/backend/apps/system/api/assistant.py @@ -14,13 +14,14 @@ from common.core.config import settings router = APIRouter(tags=["system/assistant"], prefix="/system/assistant") @router.get("/validator/{id}", response_model=AssistantValidator) -async def info(session: SessionDep, id: int): - db_model = get_assistant_info(session, id) +async def info(session: SessionDep, id: str): + as_id, flag = id.split('-') + db_model = get_assistant_info(session, as_id) if not db_model: return AssistantValidator() access_token_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES) assistantDict = { - "id": 1, "account": 'admin', "oid": 1, "assistant_id": id + "id": flag, "account": 'sqlbot-inner-assistant', "oid": 1, "assistant_id": id } access_token = create_access_token( assistantDict, expires_delta=access_token_expires diff --git a/backend/apps/system/crud/assistant.py b/backend/apps/system/crud/assistant.py index 0eeeba8c..45b55aa4 100644 --- a/backend/apps/system/crud/assistant.py +++ b/backend/apps/system/crud/assistant.py @@ -3,10 +3,14 @@ from sqlmodel import Session from apps.system.models.system_model import AssistantModel from apps.system.schemas.auth import CacheName, CacheNamespace +from apps.system.schemas.system_schema import UserInfoDTO from common.core.sqlbot_cache import cache @cache(namespace=CacheNamespace.EMBEDDED_INFO, cacheName=CacheName.ASSISTANT_INFO, keyExpression="assistant_id") async def get_assistant_info(*, session: Session, assistant_id: int) -> AssistantModel | None: db_model = session.get(AssistantModel, assistant_id) - return db_model \ No newline at end of file + return db_model + +def get_assistant_user(*, id: int): + return UserInfoDTO(id=id, account="sqlbot-inner-assistant", oid=1, name="sqlbot-inner-assistant", email="sqlbot-inner-assistant@sqlbot.com") diff --git a/backend/apps/system/middleware/auth.py b/backend/apps/system/middleware/auth.py index e821e9c7..809ba15d 100644 --- a/backend/apps/system/middleware/auth.py +++ b/backend/apps/system/middleware/auth.py @@ -6,7 +6,7 @@ import jwt from sqlmodel import Session from starlette.middleware.base import BaseHTTPMiddleware from common.core.db import engine -from apps.system.crud.assistant import get_assistant_info +from apps.system.crud.assistant import get_assistant_info, get_assistant_user from apps.system.crud.user import get_user_info from apps.system.schemas.system_schema import UserInfoDTO from common.core import security @@ -80,8 +80,9 @@ class TokenMiddleware(BaseHTTPMiddleware): return False, f"Miss assistant payload error!" try: with Session(engine) as session: - session_user = await get_user_info(session = session, user_id = token_data.id) - session_user = UserInfoDTO.model_validate(session_user) + """ session_user = await get_user_info(session = session, user_id = token_data.id) + session_user = UserInfoDTO.model_validate(session_user) """ + session_user = get_assistant_user(id = token_data.id) assistant_info = get_assistant_info(session, payload['assistant_id']) return True, session_user, assistant_info except Exception as e: diff --git a/backend/common/core/deps.py b/backend/common/core/deps.py index 85942b0f..558ad646 100644 --- a/backend/common/core/deps.py +++ b/backend/common/core/deps.py @@ -2,6 +2,7 @@ from typing import Annotated from fastapi import Depends, Request from sqlmodel import Session +from apps.system.models.system_model import AssistantModel from apps.system.schemas.system_schema import UserInfoDTO from common.core.db import get_session from common.utils.locale import I18n @@ -18,5 +19,10 @@ async def get_current_user(request: Request) -> UserInfoDTO: CurrentUser = Annotated[UserInfoDTO, Depends(get_current_user)] +async def get_current_assistant(request: Request) -> AssistantModel: + return request.state.assistant + +CurrentAssistant = Annotated[AssistantModel, Depends(get_current_assistant)] + diff --git a/frontend/src/stores/assistant.ts b/frontend/src/stores/assistant.ts index c4c986e3..d20a4c6d 100644 --- a/frontend/src/stores/assistant.ts +++ b/frontend/src/stores/assistant.ts @@ -1,10 +1,14 @@ import { defineStore } from 'pinia' import { store } from './index' import { chatApi, ChatInfo } from '@/api/chat' +import { useCache } from '@/utils/useCache' +const { wsCache } = useCache() +const flagKey = 'sqlbit-assistant-flag' interface AssistantState { token: string assistant: boolean + flag: number } export const AssistantStore = defineStore('assistant', { @@ -12,6 +16,7 @@ export const AssistantStore = defineStore('assistant', { return { token: '', assistant: false, + flag: 0, } }, getters: { @@ -21,6 +26,9 @@ export const AssistantStore = defineStore('assistant', { getAssistant(): boolean { return this.assistant }, + getFlag(): number { + return this.flag + }, }, actions: { setToken(token: string) { @@ -29,6 +37,14 @@ export const AssistantStore = defineStore('assistant', { setAssistant(assistant: boolean) { this.assistant = assistant }, + setFlag(flag: number) { + if (wsCache.get(flagKey)) { + this.flag = wsCache.get(flagKey) + } else { + this.flag = flag + wsCache.set(flagKey, flag) + } + }, async setChat() { if (!this.assistant) { return null @@ -38,6 +54,7 @@ export const AssistantStore = defineStore('assistant', { return chat }, clear() { + wsCache.delete(flagKey) this.$reset() }, }, diff --git a/frontend/src/utils/request.ts b/frontend/src/utils/request.ts index 1a26d692..39000d95 100644 --- a/frontend/src/utils/request.ts +++ b/frontend/src/utils/request.ts @@ -238,7 +238,7 @@ class HttpService { } if (assistantStore.getToken) { heads['X-SQLBOT-ASSISTANT-TOKEN'] = `Assistant ${assistantStore.getToken}` - if (heads['X-SQLBOT-TOKEN']) heads.delete('X-SQLBOT-TOKEN') + if (heads['X-SQLBOT-TOKEN']) delete heads['X-SQLBOT-TOKEN'] } // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore diff --git a/frontend/src/views/embedded/assistant.vue b/frontend/src/views/embedded/assistant.vue index 42c056b6..199940db 100644 --- a/frontend/src/views/embedded/assistant.vue +++ b/frontend/src/views/embedded/assistant.vue @@ -96,7 +96,10 @@ const validator = ref({ const loading = ref(true) onBeforeMount(async () => { const assistantId = route.params.id - validator.value = await assistantApi.validate(assistantId) + const now = Date.now() + assistantStore.setFlag(now) + const id = `${assistantId}-${assistantStore.getFlag}` + validator.value = await assistantApi.validate(id) assistantStore.setToken(validator.value.token) assistantStore.setAssistant(true) loading.value = false