apikey in header

This commit is contained in:
朱潮 2025-10-08 18:01:11 +08:00
parent 4ba950a1ea
commit d123a67da1
5 changed files with 25 additions and 1026 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@
projects/*
workspace
__pycache__
public

View File

@ -29,16 +29,17 @@ COPY . .
# 创建必要的目录
RUN mkdir -p /app/projects
RUN mkdir -p /app/public
# 设置权限
RUN chmod +x /app/mcp/json_reader_server.py
# 暴露端口
EXPOSE 8000
EXPOSE 8001
# 健康检查
HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8000/ || exit 1
CMD curl -f http://localhost:8001/ || exit 1
# 启动命令
CMD ["python", "fastapi_app.py"]

1008
chat.html

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,7 @@ services:
build: .
container_name: qwen-agent-api
ports:
- "8000:8000"
- "8001:8001"
environment:
# 应用配置
- PYTHONPATH=/app
@ -14,10 +14,11 @@ services:
volumes:
# 挂载项目数据目录
- ./projects:/app/projects
- ./public:/app/public
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/"]
test: ["CMD", "curl", "-f", "http://localhost:8001/"]
interval: 30s
timeout: 10s
retries: 3

View File

@ -3,7 +3,7 @@ import os
from typing import AsyncGenerator, Dict, List, Optional, Union
import uvicorn
from fastapi import FastAPI, HTTPException
from fastapi import FastAPI, HTTPException, Depends, Header
from fastapi.responses import StreamingResponse, HTMLResponse, FileResponse
from fastapi.staticfiles import StaticFiles
from fastapi.middleware.cors import CORSMiddleware
@ -51,6 +51,9 @@ agent_manager = init_global_agent_manager(max_cached_agents=max_cached_agents)
app = FastAPI(title="Database Assistant API", version="1.0.0")
# 挂载public文件夹为静态文件服务
app.mount("/public", StaticFiles(directory="public"), name="static")
# 添加CORS中间件支持前端页面
app.add_middleware(
CORSMiddleware,
@ -69,7 +72,6 @@ class Message(BaseModel):
class ChatRequest(BaseModel):
messages: List[Message]
model: str = "qwen3-next"
api_key: Optional[str] = None
model_server: Optional[str] = None
zip_url: Optional[str] = None
generate_cfg: Optional[Dict] = None
@ -156,18 +158,28 @@ async def generate_stream_response(agent, messages, request) -> AsyncGenerator[s
yield f"data: {json.dumps(error_data, ensure_ascii=False)}\n\n"
@app.post("/chat/completions")
async def chat_completions(request: ChatRequest):
@app.post("/api/v1/chat/completions")
async def chat_completions(request: ChatRequest, authorization: Optional[str] = Header(None)):
"""
Chat completions API similar to OpenAI, supports both streaming and non-streaming
Args:
request: ChatRequest containing messages, model, zip_url, etc.
authorization: Authorization header containing API key (Bearer <API_KEY>)
Returns:
Union[ChatResponse, StreamingResponse]: Chat completion response or stream
"""
try:
# 从Authorization header中提取API key
api_key = None
if authorization:
# 移除 "Bearer " 前缀
if authorization.startswith("Bearer "):
api_key = authorization[7:]
else:
api_key = authorization
# 从最外层获取zip_url参数
zip_url = request.zip_url
@ -191,7 +203,7 @@ async def chat_completions(request: ChatRequest):
zip_url=zip_url,
files=document_files,
model_name=request.model,
api_key=request.api_key,
api_key=api_key,
model_server=request.model_server,
generate_cfg=request.generate_cfg
)
@ -258,14 +270,6 @@ async def chat_completions(request: ChatRequest):
raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
@app.get("/")
async def root():
"""Chat page endpoint"""
return FileResponse("chat.html", media_type="text/html")
@app.get("/api/health")
async def health_check():
"""Health check endpoint"""
@ -353,4 +357,4 @@ async def remove_project_cache(zip_url: str):
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)
uvicorn.run(app, host="0.0.0.0", port=8001)