Skip to content

Commit 178d41a

Browse files
feat: AI Model
1 parent 2de7ece commit 178d41a

File tree

15 files changed

+766
-23
lines changed

15 files changed

+766
-23
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
"""004_add_aimodel_auto
2+
3+
Revision ID: 8fe654655905
4+
Revises: d116056121c3
5+
Create Date: 2025-05-07 15:51:34.768842
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 = '8fe654655905'
15+
down_revision = 'd116056121c3'
16+
branch_labels = None
17+
depends_on = None
18+
19+
20+
def upgrade():
21+
# ### commands auto generated by Alembic - please adjust! ###
22+
op.create_table('ai_model',
23+
sa.Column('id', sa.BigInteger(), nullable=False),
24+
sa.Column('name', sqlmodel.sql.sqltypes.AutoString(length=255), nullable=False),
25+
sa.Column('type', sa.Integer(), nullable=False),
26+
sa.Column('api_key', sqlmodel.sql.sqltypes.AutoString(length=255), nullable=True),
27+
sa.Column('endpoint', sqlmodel.sql.sqltypes.AutoString(length=255), nullable=False),
28+
sa.Column('max_context_window', sa.Integer(), nullable=False),
29+
sa.Column('temperature', sa.Float(), nullable=False),
30+
sa.Column('status', sa.Boolean(), nullable=False),
31+
sa.Column('description', sqlmodel.sql.sqltypes.AutoString(length=255), nullable=True),
32+
sa.Column('create_time', sa.BigInteger(), nullable=False),
33+
sa.PrimaryKeyConstraint('id')
34+
)
35+
op.create_index(op.f('ix_ai_model_id'), 'ai_model', ['id'], unique=False)
36+
# ### end Alembic commands ###
37+
38+
39+
def downgrade():
40+
# ### commands auto generated by Alembic - please adjust! ###
41+
op.drop_index(op.f('ix_ai_model_id'), table_name='ai_model')
42+
op.drop_table('ai_model')
43+
# ### end Alembic commands ###

backend/apps/api.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
from fastapi import APIRouter
22

3-
from apps.system.api import login, user
3+
from apps.system.api import login, user, aimodel
44
from apps.settings.api import terminology
55
from apps.datasource.api import datasource
66

77

88
api_router = APIRouter()
99
api_router.include_router(login.router)
1010
api_router.include_router(user.router)
11+
api_router.include_router(aimodel.router)
1112
api_router.include_router(terminology.router)
1213
api_router.include_router(datasource.router)
1314

backend/apps/system/api/aimodel.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
from datetime import datetime
2+
from fastapi import APIRouter
3+
from sqlmodel import select
4+
from apps.system.models.system_modle import AiModelDetail
5+
from apps.system.schemas.system_schema import model_status
6+
from common.core.deps import SessionDep
7+
from common.core.pagination import Paginator
8+
from common.core.schemas import PaginatedResponse, PaginationParams
9+
from common.utils.time import get_timestamp
10+
11+
router = APIRouter(tags=["system/aimodel"], prefix="/system/aimodel")
12+
13+
14+
@router.get("/pager/{pageNum}/{pageSize}", response_model=PaginatedResponse[AiModelDetail])
15+
async def pager(
16+
session: SessionDep,
17+
pageNum: int,
18+
pageSize: int
19+
):
20+
pagination = PaginationParams(page=pageNum, size=pageSize)
21+
paginator = Paginator(session)
22+
filters = {}
23+
return await paginator.get_paginated_response(
24+
model=AiModelDetail,
25+
pagination=pagination,
26+
**filters)
27+
28+
@router.get("/{id}", response_model=AiModelDetail)
29+
async def get_model_by_id(
30+
session: SessionDep,
31+
id: int
32+
):
33+
term = session.get(AiModelDetail, id)
34+
return term
35+
36+
@router.post("", response_model=AiModelDetail)
37+
async def add_model(
38+
session: SessionDep,
39+
creator: AiModelDetail
40+
):
41+
data = AiModelDetail.model_validate(creator)
42+
data.create_time = get_timestamp()
43+
session.add(data)
44+
session.commit()
45+
return creator
46+
47+
@router.put("", response_model=AiModelDetail)
48+
async def update_terminology(
49+
session: SessionDep,
50+
model: AiModelDetail
51+
):
52+
model.id = int(model.id)
53+
term = session.exec(select(AiModelDetail).where(AiModelDetail.id == model.id)).first()
54+
update_data = model.model_dump(exclude_unset=True)
55+
for field, value in update_data.items():
56+
setattr(term, field, value)
57+
session.add(term)
58+
session.commit()
59+
return model
60+
61+
@router.delete("/{id}", response_model=AiModelDetail)
62+
async def delete_terminology(
63+
session: SessionDep,
64+
id: int
65+
):
66+
term = session.exec(select(AiModelDetail).where(AiModelDetail.id == id)).first()
67+
session.delete(term)
68+
session.commit()
69+
return {
70+
"message": f"AiModel with ID {id} deleted successfully."
71+
}
72+
73+
74+
@router.patch("/status", response_model=dict)
75+
async def status(session: SessionDep, dto: model_status):
76+
ids = dto.ids
77+
status = dto.status
78+
if not ids:
79+
return {"message": "ids is empty"}
80+
statement = select(AiModelDetail).where(AiModelDetail.id.in_(ids))
81+
terms = session.exec(statement).all()
82+
for term in terms:
83+
term.status = status
84+
session.add(term)
85+
session.commit()
86+
return {"message": f"AiModel with IDs {ids} updated successfully."}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
2+
from sqlmodel import BigInteger, Field, SQLModel
3+
from common.core.models import SnowflakeBase
4+
5+
6+
class AiModelBase:
7+
name: str = Field(max_length=255, nullable=False)
8+
type: int = Field(nullable=False)
9+
10+
class AiModelDetail(AiModelBase, SnowflakeBase, table=True):
11+
__tablename__ = "ai_model"
12+
api_key: str | None = Field(max_length=255, nullable=True)
13+
endpoint: str = Field(max_length=255, nullable=False)
14+
max_context_window: int = Field(default=0)
15+
temperature: float = Field(default=0.0)
16+
status: bool = Field(default=True)
17+
description: str | None = Field(max_length=255, nullable=True)
18+
create_time: int = Field(default=0, sa_type=BigInteger())
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from pydantic import BaseModel
2+
3+
class model_status(BaseModel):
4+
status: bool
5+
ids: list[int]

backend/common/core/models.py

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,7 @@ class SnowflakeBase(SQLModel):
1313
nullable=False
1414
)
1515

16-
@field_validator("id", mode="before")
17-
def validate_id(cls, v):
18-
if isinstance(v, str):
19-
if not v:
20-
return None
21-
try:
22-
return int(v)
23-
except ValueError:
24-
raise ValueError("Invalid bigint string")
25-
elif isinstance(v, int):
26-
return v
27-
raise TypeError("BigInt must be int or string")
28-
29-
3016
class Config:
3117
json_encoders = {
32-
int: lambda v: str(v) if v > 2**53-1 else v
18+
int: lambda v: str(v) if isinstance(v, int) and v > (2**53 - 1) else v
3319
}

backend/common/utils/time.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from datetime import datetime
2+
3+
4+
def get_timestamp():
5+
dt_millis = int(datetime.now().timestamp() * 1000)
6+
return dt_millis

backend/scripts/alembic/auto.sh

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#!/bin/bash
2+
3+
RED='\033[0;31m'
4+
GREEN='\033[0;32m'
5+
NC='\033[0m' # No Color
6+
7+
usage() {
8+
echo -e "${GREEN}Usage:${NC} $0 [\"migration message\"]"
9+
echo -e "Example: $0 \"Added user table\""
10+
exit 1
11+
}
12+
13+
if [ "$#" -eq 0 ]; then
14+
echo -e "${RED}Error:${NC} No migration message provided"
15+
usage
16+
fi
17+
18+
echo -e "${GREEN}Generating migration with message:${NC} \"$1\""
19+
alembic revision --autogenerate -m "$1"
20+
21+
if [ $? -eq 0 ]; then
22+
echo -e "${GREEN}Migration created successfully!${NC}"
23+
else
24+
echo -e "${RED}Error:${NC} Failed to create migration"
25+
exit 1
26+
fi

frontend/components.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ declare module 'vue' {
1111
ElAvatar: typeof import('element-plus/es')['ElAvatar']
1212
ElButton: typeof import('element-plus/es')['ElButton']
1313
ElCard: typeof import('element-plus/es')['ElCard']
14+
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
1415
ElDialog: typeof import('element-plus/es')['ElDialog']
1516
ElDropdown: typeof import('element-plus/es')['ElDropdown']
1617
ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
@@ -22,7 +23,9 @@ declare module 'vue' {
2223
ElMenu: typeof import('element-plus/es')['ElMenu']
2324
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
2425
ElOption: typeof import('element-plus/es')['ElOption']
26+
ElPagination: typeof import('element-plus/es')['ElPagination']
2527
ElSelect: typeof import('element-plus/es')['ElSelect']
28+
ElSlider: typeof import('element-plus/es')['ElSlider']
2629
ElTable: typeof import('element-plus/es')['ElTable']
2730
ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
2831
ElTabPane: typeof import('element-plus/es')['ElTabPane']

frontend/src/api/system.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { request } from '@/utils/request'
2+
3+
export const modelApi = {
4+
pager: (pageNumber: number, pageSize: number) => request.get(`/system/aimodel/pager/${pageNumber}/${pageSize}`),
5+
add: (data: any) => request.post('/system/aimodel', data),
6+
edit: (data: any) => request.put('/system/aimodel', data),
7+
delete: (id: number) => request.delete(`/system/aimodel/${id}`),
8+
query: (id: number) => request.get(`/system/aimodel/${id}`),
9+
status: (data: any) => request.patch('/system/aimodel/status', data),
10+
}

0 commit comments

Comments
 (0)