1
0

feat: 初始化 AI Gateway 项目

实现支持 OpenAI 和 Anthropic 双协议的统一大模型 API 网关 MVP 版本,包含:
- OpenAI 和 Anthropic 协议代理
- 供应商和模型管理
- 用量统计
- 前端配置界面
This commit is contained in:
2026-04-15 16:53:28 +08:00
commit 915b004924
53 changed files with 5662 additions and 0 deletions

119
backend/cmd/server/main.go Normal file
View File

@@ -0,0 +1,119 @@
package main
import (
"context"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"github.com/gin-gonic/gin"
"nex/backend/internal/config"
"nex/backend/internal/handler"
)
func main() {
// 初始化数据库
if err := config.InitDB(); err != nil {
log.Fatalf("初始化数据库失败: %v", err)
}
defer config.CloseDB()
// 创建 Gin 引擎
gin.SetMode(gin.ReleaseMode)
r := gin.Default()
// 配置 CORS
r.Use(func(c *gin.Context) {
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
if c.Request.Method == "OPTIONS" {
c.AbortWithStatus(204)
return
}
c.Next()
})
// 注册路由
setupRoutes(r)
// 创建 HTTP 服务器
srv := &http.Server{
Addr: ":9826",
Handler: r,
}
// 启动服务器(在 goroutine 中)
go func() {
log.Printf("AI Gateway 启动在端口 9826")
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("服务器启动失败: %v", err)
}
}()
// 等待中断信号以优雅关闭服务器
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
log.Println("正在关闭服务器...")
// 给服务器 5 秒时间完成当前请求
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := srv.Shutdown(ctx); err != nil {
log.Fatal("服务器强制关闭:", err)
}
log.Println("服务器已关闭")
}
// setupRoutes 配置路由
func setupRoutes(r *gin.Engine) {
// OpenAI 协议代理
openaiHandler := handler.NewOpenAIHandler()
r.POST("/v1/chat/completions", openaiHandler.HandleChatCompletions)
// Anthropic 协议代理
anthropicHandler := handler.NewAnthropicHandler()
r.POST("/v1/messages", anthropicHandler.HandleMessages)
// 供应商管理 API
providerHandler := handler.NewProviderHandler()
providers := r.Group("/api/providers")
{
providers.GET("", providerHandler.ListProviders)
providers.POST("", providerHandler.CreateProvider)
providers.GET("/:id", providerHandler.GetProvider)
providers.PUT("/:id", providerHandler.UpdateProvider)
providers.DELETE("/:id", providerHandler.DeleteProvider)
}
// 模型管理 API
modelHandler := handler.NewModelHandler()
models := r.Group("/api/models")
{
models.GET("", modelHandler.ListModels)
models.POST("", modelHandler.CreateModel)
models.GET("/:id", modelHandler.GetModel)
models.PUT("/:id", modelHandler.UpdateModel)
models.DELETE("/:id", modelHandler.DeleteModel)
}
// 统计查询 API
statsHandler := handler.NewStatsHandler()
stats := r.Group("/api/stats")
{
stats.GET("", statsHandler.GetStats)
stats.GET("/aggregate", statsHandler.AggregateStats)
}
// 健康检查
r.GET("/health", func(c *gin.Context) {
c.JSON(200, gin.H{"status": "ok"})
})
}