diff --git a/Dockerfile b/Dockerfile index ba8bc46..4c7c808 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,7 +10,7 @@ RUN CGO_ENABLED=0 go build -ldflags="-w -s" -o override FROM alpine:latest -RUN apk --no-cache add ca-certificates +RUN apk --no-cache add ca-certificates tzdata && cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo "Asia/Shanghai" > /etc/timezone COPY --from=builder /app/override /usr/local/bin/ COPY config.json.example /app/config.json diff --git a/docker-compose.yml b/docker-compose.yml index 296fe21..855e063 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,9 +4,9 @@ services: container_name: override-app restart: always build: - context: . - dockerfile: Dockerfile + context: . + dockerfile: Dockerfile volumes: - ./config.json:/app/config.json ports: - - "8181:8181" + - "8181:8181" diff --git a/main.go b/main.go index 97d60e0..7b5362c 100644 --- a/main.go +++ b/main.go @@ -10,8 +10,10 @@ import ( "github.com/tidwall/gjson" "github.com/tidwall/sjson" "golang.org/x/net/http2" + "html/template" "io" "log" + "math/rand" "net/http" "net/url" "os" @@ -19,7 +21,6 @@ import ( "strconv" "strings" "time" - "math/rand" ) const DefaultInstructModel = "gpt-3.5-turbo-instruct" @@ -51,6 +52,17 @@ type config struct { AuthToken string `json:"auth_token"` } +// 转换结构体为键值对 Map +func structToMap(cfg config) map[string]interface{} { + result := make(map[string]interface{}) + v := reflect.ValueOf(cfg) + t := reflect.TypeOf(cfg) + for i := 0; i < v.NumField(); i++ { + result[t.Field(i).Name] = v.Field(i).Interface() + } + return result +} + func readConfig() *config { var configPath string if len(os.Args) > 1 { @@ -194,6 +206,7 @@ func (s *ProxyService) InitRoutes(e *gin.Engine) { e.GET("/_ping", s.pong) e.GET("/models", s.models) e.GET("/v1/models", s.models) + e.GET("/", s.index) authToken := s.cfg.AuthToken // replace with your dynamic value as needed if authToken != "" { // 鉴权 @@ -220,6 +233,18 @@ type Pong struct { Ns1 string `json:"ns1"` } +func (s *ProxyService) index(c *gin.Context) { + cfg := *readConfig() + if c.Query("format") == "json" { + c.JSON(http.StatusOK, cfg) + } else { + c.HTML(http.StatusOK, "configPage", gin.H{ + "Config": structToMap(cfg), + }) + + } +} + func (s *ProxyService) pong(c *gin.Context) { c.JSON(http.StatusOK, Pong{ Now: time.Now().Second(), @@ -478,7 +503,7 @@ func (s *ProxyService) completions(c *gin.Context) { } func contains(arr []string, str string) bool { - return strings.Contains(strings.Join(arr, ","), str) + return strings.Contains(strings.Join(arr, ","), str) } func (s *ProxyService) codeCompletions(c *gin.Context) { @@ -506,7 +531,7 @@ func (s *ProxyService) codeCompletions(c *gin.Context) { } req.Header.Set("Content-Type", "application/json") - req.Header.Set("Authorization", "Bearer " + getRandomApiKey(s.cfg.CodexApiKey)) + req.Header.Set("Authorization", "Bearer "+getRandomApiKey(s.cfg.CodexApiKey)) if "" != s.cfg.CodexApiOrganization { req.Header.Set("OpenAI-Organization", s.cfg.CodexApiOrganization) } @@ -547,12 +572,12 @@ func (s *ProxyService) codeCompletions(c *gin.Context) { // 随机取一个apiKey func getRandomApiKey(paramStr string) string { - params := strings.Split(paramStr, ",") - rand.Seed(time.Now().UnixNano()) - randomIndex := rand.Intn(len(params)) + params := strings.Split(paramStr, ",") + rand.Seed(time.Now().UnixNano()) + randomIndex := rand.Intn(len(params)) fmt.Println("Code completion API Key index:", randomIndex) fmt.Println("Code completion API Key:", strings.TrimSpace(params[randomIndex])) - return strings.TrimSpace(params[randomIndex]) + return strings.TrimSpace(params[randomIndex]) } func ConstructRequestBody(body []byte, cfg *config) []byte { @@ -607,12 +632,73 @@ func constructWithChatModel(body []byte, messages interface{}) []byte { return []byte(jsonStr) } +func getHTMLTemplate() string { + return ` + + +
+ + +Below is the configuration data:
+| Key | +Value | +
|---|---|
| {{ $key }} | +{{ $value }} | +