Browse Source

change ai

master
godo 6 months ago
parent
commit
b2b3bab4f3
  1. 21
      frontend/src/system/config.ts
  2. 30
      godo/ai/api/openai.go
  3. 2
      godo/ai/llms/gitee.go
  4. 8
      godo/ai/llms/ollama.go
  5. 114
      godo/ai/llms/openai.go
  6. 52
      godo/ai/server/chat.go
  7. 7
      godo/ai/server/common.go
  8. 2
      godo/ai/server/down.go
  9. 4
      godo/ai/server/ollama.go

21
frontend/src/system/config.ts

@ -160,22 +160,11 @@ export const getSystemConfig = (ifset = false) => {
if (!config.openaiUrl) { if (!config.openaiUrl) {
config.openaiUrl = 'https://api.openai.com/v1' config.openaiUrl = 'https://api.openai.com/v1'
} }
if (!config.aiKey) { if (!config.openaiSecret) {
config.aiKey = { config.openaiSecret = ""
"openai": "", }
"gitee": "", if(!config.giteeSecret){
// "google": "", config.giteeSecret = ""
// "baidu": "",
// "ali": "",
// "tencent": "",
// "bigmodel": "",
// "xai": "",
// "azure": "",
// "stability": "",
// "claude": "",
// "groq": ""
}
} }
// 初始化桌面快捷方式列表,若本地存储中已存在则不进行覆盖 // 初始化桌面快捷方式列表,若本地存储中已存在则不进行覆盖
if (!config.desktopList) { if (!config.desktopList) {

30
godo/ai/api/openai.go

@ -1,30 +0,0 @@
package api
import (
"fmt"
"godo/libs"
)
// 获取 OpenAI 聊天 API 的 URL
func GetOpenAIChatUrl() string {
return "https://api.openai.com/v1/chat/completions"
}
// 获取 OpenAI 文本嵌入 API 的 URL
func GetOpenAIEmbeddingUrl() string {
return "https://api.openai.com/v1/embeddings"
}
// 获取 OpenAI 文本转图像 API 的 URL
func GetOpenAIText2ImgUrl() string {
return "https://api.openai.com/v1/images/generations"
}
// 获取 OpenAI 密钥
func GetOpenAISecret() (string, error) {
secret, has := libs.GetConfig("openaiSecret")
if !has {
return "", fmt.Errorf("the openai secret is not set")
}
return secret.(string), nil
}

2
godo/ai/api/gitee.go → godo/ai/llms/gitee.go

@ -1,4 +1,4 @@
package api package llms
import ( import (
"fmt" "fmt"

8
godo/ai/llms/ollama.go

@ -0,0 +1,8 @@
package llms
func GetOllamaChatUrl(url string) string {
return url + "/v1/chat/completions"
}
func GetOllamaEmbeddingUrl(url string) string {
return url + "/api/embeddings"
}

114
godo/ai/llms/openai.go

@ -0,0 +1,114 @@
package llms
import (
"fmt"
"godo/libs"
)
// ollama openai deepseek bigmodel alibaba 01ai cloudflare groq mistral anthropic llamafamily
var OpenAIApiMaps = map[string]string{
//"openai": GetOpenAIUrl(),
"deepseek": "https://api.deepseek.com/v1",
"bigmodel": "https://open.bigmodel.cn/api/paas/v4",
"alibaba": "https://dashscope.aliyuncs.com/compatible-mode/v1",
"01ai": "https://api.lingyiwanwu.com/v1",
"groq": "https://api.groq.com/openai/v1",
"mistral": "https://api.mistral.ai/v1",
"anthropic": "https://api.anthropic.com/v1",
"llamafamily": "https://api.atomecho.cn/v1",
}
// 获取 OpenAI 聊天 API 的 URL
func GetOpenAIChatUrl(types string) (map[string]string, string, error) {
aiUrl, err := GetAIUrl(types)
if err != nil {
return nil, "", err
}
headers, err := GetOpenAIHeaders(types)
if err != nil {
return nil, "", err
}
return headers, aiUrl + "/chat/completions", nil
}
// 获取 OpenAI 文本嵌入 API 的 URL
func GetOpenAIEmbeddingUrl(types string) (map[string]string, string, error) {
aiUrl, err := GetAIUrl(types)
if err != nil {
return nil, "", err
}
headers, err := GetOpenAIHeaders(types)
if err != nil {
return nil, "", err
}
return headers, aiUrl + "/embeddings", nil
}
// 获取 OpenAI 文本转图像 API 的 URL
func GetOpenAIText2ImgUrl(types string) (map[string]string, string, error) {
aiUrl, err := GetAIUrl(types)
if err != nil {
return nil, "", err
}
headers, err := GetOpenAIHeaders(types)
if err != nil {
return nil, "", err
}
return headers, aiUrl + "/images/generations", nil
}
func GetAIUrl(types string) (string, error) {
if types == "openai" {
return GetOpenAIUrl(), nil
} else if types == "cloudflare" {
return GetCloudflareUrl()
} else {
url, exists := OpenAIApiMaps[types]
if !exists {
return "", fmt.Errorf("the " + types + " url is not set")
} else {
return url, nil
}
}
}
func GetOpenAIHeaders(types string) (map[string]string, error) {
secret, err := GetOpenAISecret(types)
if err != nil {
return nil, err
}
return map[string]string{
"Content-Type": "application/json",
"Authorization": "Bearer " + secret,
}, nil
}
// 获取 OpenAI 密钥
func GetOpenAISecret(types string) (string, error) {
secret, has := libs.GetConfig(types + "Secret")
if !has {
return "", fmt.Errorf("the " + types + " secret is not set")
}
return secret.(string), nil
}
func GetOpenAIUserId(types string) (string, error) {
userId, has := libs.GetConfig(types + "UserId")
if !has {
return "", fmt.Errorf("the " + types + " user id is not set")
}
return userId.(string), nil
}
func GetOpenAIUrl() string {
openaiUrl, ok := libs.GetConfig("openaiUrl")
if ok {
return openaiUrl.(string)
} else {
return "https://api.openai.com/v1"
}
}
func GetCloudflareUrl() (string, error) {
userId, err := GetOpenAIUserId("cloudflare")
if err != nil {
return "", err
}
return "https://api.cloudflare.com/client/v4/accounts/" + userId + "/ai/v1", nil
}

52
godo/ai/server/chat.go

@ -2,20 +2,62 @@ package server
import ( import (
"encoding/json" "encoding/json"
"godo/ai/llms"
"godo/libs" "godo/libs"
"net/http" "net/http"
) )
func ChatHandler(w http.ResponseWriter, r *http.Request) { func ChatHandler(w http.ResponseWriter, r *http.Request) {
url := GetOllamaUrl() + "/v1/chat/completions" // url := GetOllamaUrl() + "/v1/chat/completions"
var request interface{} var url string
err := json.NewDecoder(r.Body).Decode(&request) var req map[string]interface{}
err := json.NewDecoder(r.Body).Decode(&req)
if err != nil { if err != nil {
libs.ErrorMsg(w, err.Error()) libs.ErrorMsg(w, err.Error())
return return
} }
ForwardHandler(w, r, request, url, "POST") engine, ok := req["engine"].(string)
if !ok {
libs.ErrorMsg(w, "Invalid engine field in request")
return
}
model, ok := req["model"].(string)
if !ok {
libs.ErrorMsg(w, "Invalid model field in request")
return
}
var headers map[string]string
switch engine {
case "ollama":
ollamaUrl := GetOllamaUrl()
url = llms.GetOllamaChatUrl(ollamaUrl)
headers = map[string]string{
"Content-Type": "application/json",
}
case "gitee":
url = llms.GetGiteeChatUrl(model)
case "openai":
headers, url, err = llms.GetOpenAIChatUrl("openai")
if err != nil {
libs.ErrorMsg(w, err.Error())
return
}
case "cloudflare":
headers, url, err = llms.GetOpenAIChatUrl("cloudflare")
if err != nil {
libs.ErrorMsg(w, err.Error())
return
}
default:
headers, url, err = llms.GetOpenAIChatUrl("openai") // 默认URL
if err != nil {
libs.ErrorMsg(w, err.Error())
return
}
}
ForwardHandler(w, r, req, url, headers, "POST")
} }
func EmbeddingHandler(w http.ResponseWriter, r *http.Request) { func EmbeddingHandler(w http.ResponseWriter, r *http.Request) {
url := GetOllamaUrl() + "/api/embeddings" url := GetOllamaUrl() + "/api/embeddings"
var request interface{} var request interface{}
@ -24,5 +66,5 @@ func EmbeddingHandler(w http.ResponseWriter, r *http.Request) {
libs.ErrorMsg(w, err.Error()) libs.ErrorMsg(w, err.Error())
return return
} }
ForwardHandler(w, r, request, url, "POST") ForwardHandler(w, r, request, url, nil, "POST")
} }

7
godo/ai/server/common.go

@ -9,7 +9,7 @@ import (
"net/http" "net/http"
) )
func ForwardHandler(w http.ResponseWriter, r *http.Request, reqBody interface{}, url string, method string) { func ForwardHandler(w http.ResponseWriter, r *http.Request, reqBody interface{}, url string, headers map[string]string, method string) {
payloadBytes, err := json.Marshal(reqBody) payloadBytes, err := json.Marshal(reqBody)
if err != nil { if err != nil {
libs.ErrorMsg(w, "Error marshaling payload") libs.ErrorMsg(w, "Error marshaling payload")
@ -21,7 +21,10 @@ func ForwardHandler(w http.ResponseWriter, r *http.Request, reqBody interface{},
libs.ErrorMsg(w, "Failed to create request") libs.ErrorMsg(w, "Failed to create request")
return return
} }
req.Header.Set("Content-Type", "application/json") for key, value := range headers {
req.Header.Set(key, value)
}
//req.Header.Set("Content-Type", "application/json")
// 发送请求 // 发送请求
client := &http.Client{} client := &http.Client{}

2
godo/ai/server/down.go

@ -223,7 +223,7 @@ func DeleteFileHandle(w http.ResponseWriter, r *http.Request) {
postQuery := map[string]interface{}{"name": reqBody.Model} postQuery := map[string]interface{}{"name": reqBody.Model}
url := GetOllamaUrl() + "/api/delete" url := GetOllamaUrl() + "/api/delete"
ForwardHandler(w, r, postQuery, url, "DELETE") ForwardHandler(w, r, postQuery, url, nil, "DELETE")
return return
} }
delUrls(reqBody.Info.URL) delUrls(reqBody.Info.URL)

4
godo/ai/server/ollama.go

@ -177,7 +177,7 @@ func setOllamaInfo(w http.ResponseWriter, r *http.Request, reqBody types.ReqBody
"model": model, "model": model,
} }
url := GetOllamaUrl() + "/api/pull" url := GetOllamaUrl() + "/api/pull"
ForwardHandler(w, r, postQuery, url, "POST") ForwardHandler(w, r, postQuery, url, nil, "POST")
details, err := getOllamaInfo(r, model) details, err := getOllamaInfo(r, model)
//log.Printf("details is %v", details) //log.Printf("details is %v", details)
if err != nil { if err != nil {
@ -366,7 +366,7 @@ func ConvertOllama(w http.ResponseWriter, r *http.Request, req types.ReqBody) {
"name": req.Model, "name": req.Model,
"modelfile": modelFile, "modelfile": modelFile,
} }
ForwardHandler(w, r, postParams, url, "POST") ForwardHandler(w, r, postParams, url, nil, "POST")
modelDir, err := config.GetModelDir(req.Model) modelDir, err := config.GetModelDir(req.Model)
if err != nil { if err != nil {
libs.ErrorMsg(w, "GetModelDir") libs.ErrorMsg(w, "GetModelDir")

Loading…
Cancel
Save