perf: Assistant

This commit is contained in:
fit2cloud-chenyw
2025-07-16 11:29:48 +08:00
parent bf9bec3259
commit 070f556af0
6 changed files with 57 additions and 28 deletions
+22 -7
View File
@@ -1,5 +1,6 @@
from datetime import timedelta
from fastapi import APIRouter, FastAPI, Request
from typing import Optional
from fastapi import APIRouter, FastAPI, Query, Request, Response
from sqlmodel import Session, select
from apps.system.crud.assistant import get_assistant_info
from apps.system.models.system_model import AssistantModel
@@ -13,15 +14,28 @@ from starlette.middleware.cors import CORSMiddleware
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: str):
as_id, flag = id.split('-')
db_model = get_assistant_info(session, as_id)
@router.get("/info/{id}")
async def info(request: Request, response: Response, session: SessionDep, id: int) -> dict:
db_model = await get_assistant_info(session=session, assistant_id=id)
if not db_model:
raise RuntimeError(f"assistant application not exist")
db_model = AssistantModel.model_validate(db_model)
response.headers["Access-Control-Allow-Origin"] = db_model.domain
origin = request.headers.get("origin") or request.headers.get("referer")
origin = origin.rstrip('/')
""" if origin != db_model.domain:
raise RuntimeError("invalid domain [{origin}]") """
return db_model.model_dump()
@router.get("/validator", response_model=AssistantValidator)
async def info(session: SessionDep, id: str, virtual: Optional[int] = Query(None), online: Optional[bool] = Query(default=False)):
db_model = await get_assistant_info(session=session, assistant_id=id)
if not db_model:
return AssistantValidator()
db_model = AssistantModel.model_validate(db_model)
access_token_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
assistantDict = {
"id": flag, "account": 'sqlbot-inner-assistant', "oid": 1, "assistant_id": id
"id": virtual, "account": 'sqlbot-inner-assistant', "oid": 1, "assistant_id": id
}
access_token = create_access_token(
assistantDict, expires_delta=access_token_expires
@@ -58,9 +72,10 @@ async def update(request: Request, session: SessionDep, editor: AssistantDTO):
@router.get("/{id}", response_model=AssistantModel)
async def get_one(session: SessionDep, id: int):
db_model = get_assistant_info(session, id)
db_model = await get_assistant_info(session=session, assistant_id=id)
if not db_model:
raise ValueError(f"AssistantModel with id {id} not found")
db_model = AssistantModel.model_validate(db_model)
return db_model
@router.delete("/{id}")
+9 -7
View File
@@ -5,6 +5,7 @@ from fastapi.responses import JSONResponse
import jwt
from sqlmodel import Session
from starlette.middleware.base import BaseHTTPMiddleware
from apps.system.models.system_model import AssistantModel
from common.core.db import engine
from apps.system.crud.assistant import get_assistant_info, get_assistant_user
from apps.system.crud.user import get_user_info
@@ -29,12 +30,12 @@ class TokenMiddleware(BaseHTTPMiddleware):
assistantToken = request.headers.get(assistantTokenKey)
#if assistantToken and assistantToken.lower().startswith("assistant "):
if assistantToken:
validate_pass, data, assistant = await self.validateAssistant(assistantToken)
if validate_pass:
request.state.current_user = data
request.state.assistant = assistant
validator: tuple[any] = await self.validateAssistant(assistantToken)
if validator[0]:
request.state.current_user = validator[1]
request.state.assistant = validator[2]
return await call_next(request)
return JSONResponse({"error": f"Unauthorized:[{data}]"}, status_code=401)
return JSONResponse({"error": f"Unauthorized:[{validator[1]}]"}, status_code=401)
#validate pass
tokenkey = settings.TOKEN_KEY
token = request.headers.get(tokenkey)
@@ -66,7 +67,7 @@ class TokenMiddleware(BaseHTTPMiddleware):
return False, e
async def validateAssistant(self, assistantToken: Optional[str]):
async def validateAssistant(self, assistantToken: Optional[str]) -> tuple[any]:
if not assistantToken:
return False, f"Miss Token[{settings.TOKEN_KEY}]!"
schema, param = get_authorization_scheme_param(assistantToken)
@@ -83,7 +84,8 @@ class TokenMiddleware(BaseHTTPMiddleware):
""" 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'])
assistant_info = await get_assistant_info(session=session, assistant_id=payload['assistant_id'])
assistant_info = AssistantModel.model_validate(assistant_info)
return True, session_user, assistant_info
except Exception as e:
return False, e
+2 -1
View File
@@ -26,7 +26,8 @@ wlist = [
"/system/config/key",
"/images/*",
"/sse",
"/system/assistant/validator/*"
"/system/assistant/validator*",
"/system/assistant/info/*"
]
class WhitelistChecker:
+17 -10
View File
@@ -3,7 +3,7 @@
id: '1',
show_guide: false,
float_icon: '',
domain_url: 'http://localhost:5173/',
domain_url: 'http://localhost:5173',
header_font_color: 'rgb(100, 106, 115)',
x_type: 'right',
y_type: 'bottom',
@@ -40,7 +40,7 @@
const getChatContainerHtml = (data) => {
return `
<div id="sqlbot-assistant-chat-container">
<iframe id="sqlbot-assistant-chat" allow="microphone" src="${data.domain_url}#/assistant?id=${data.id}"></iframe>
<iframe id="sqlbot-assistant-chat" allow="microphone" src="${data.domain_url}/#/assistant?id=${data.id}"></iframe>
<div class="sqlbot-assistant-operate">
<div class="sqlbot-assistant-closeviewport sqlbot-assistant-viewportnone">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none">
@@ -337,19 +337,26 @@
function loadScript(src, id) {
const domain_url = getDomain(src)
// const url = `${domain_url}api/v1/system/assistant/validator/${id}`
/* const url = `http://localhost:8000/api/v1/system/assistant/validator/${id}`
let url = `${domain_url}/api/v1/system/assistant/info/${id}`
if (domain_url.includes('5173')) {
url = url.replace('5173', '8000')
}
fetch(url)
.then((response) => response.json())
.then((data) => {
console.log(data)
const tempData = Object.assign(defaultData, data)
.then((res) => {
const data = res.data
const config_json = data.configuration
let tempData = Object.assign(defaultData, { id, domain_url })
if (config_json) {
const config = JSON.parse(config_json)
Object.assign(tempData, config)
tempData = Object.assign(tempData, config)
}
initsqlbot_assistant(tempData)
}) */
initsqlbot_assistant(defaultData)
})
}
function getDomain(src) {
return src.substring(0, src.indexOf('assistant.js'))
return src.substring(0, src.indexOf('/assistant.js'))
}
function init() {
const sqlbotScripts = document.querySelectorAll(`script[id^="${script_id_prefix}"]`)
+1 -1
View File
@@ -7,5 +7,5 @@ export const assistantApi = {
edit: (data: any) => request.put('/system/assistant', data),
delete: (id: number) => request.delete(`/system/assistant/${id}`),
query: (id: number) => request.get(`/system/assistant/${id}`),
validate: (id: any) => request.get(`/system/assistant/validator/${id}`),
validate: (data: any) => request.get('/system/assistant/validator', { params: data }),
}
+6 -2
View File
@@ -100,8 +100,12 @@ onBeforeMount(async () => {
console.log(online)
const now = Date.now()
assistantStore.setFlag(now)
const id = `${assistantId}-${assistantStore.getFlag}`
validator.value = await assistantApi.validate(id)
const param = {
id: assistantId,
virtual: assistantStore.getFlag,
online,
}
validator.value = await assistantApi.validate(param)
assistantStore.setToken(validator.value.token)
assistantStore.setAssistant(true)
loading.value = false