Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
102 changes: 94 additions & 8 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,17 @@ 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"
"reflect"
"strconv"
"strings"
"time"
"math/rand"
)

const DefaultInstructModel = "gpt-3.5-turbo-instruct"
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 != "" {
// 鉴权
Expand All @@ -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(),
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -607,12 +632,73 @@ func constructWithChatModel(body []byte, messages interface{}) []byte {
return []byte(jsonStr)
}

func getHTMLTemplate() string {
return `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Config Page</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
padding: 0;
}
.container {
max-width: 800px;
margin: 0 auto;
}
table {
width: 100%;
border-collapse: collapse;
margin: 20px 0;
}
table, th, td {
border: 1px solid #ccc;
}
th, td {
padding: 10px;
text-align: left;
}
th {
background-color: #f4f4f4;
}
</style>
</head>
<body>
<div class="container">
<h1>Configuration</h1>
<p>Below is the configuration data:</p>
<table>
<thead>
<tr>
<th>Key</th>
<th>Value</th>
</tr>
</thead>
<tbody>
{{ range $key, $value := .Config }}
<tr>
<td>{{ $key }}</td>
<td>{{ $value }}</td>
</tr>
{{ end }}
</tbody>
</table>
</div>
</body>
</html>
`
}

func main() {
cfg := readConfig()

gin.SetMode(gin.ReleaseMode)
r := gin.Default()

r.SetHTMLTemplate(template.Must(template.New("configPage").Parse(getHTMLTemplate())))
proxyService, err := NewProxyService(cfg)
if nil != err {
log.Fatal(err)
Expand Down