Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
Vanessa 2023-03-03 22:51:15 +08:00
commit 3f95ee9527
6 changed files with 156 additions and 0 deletions

38
kernel/api/ai.go Normal file
View file

@ -0,0 +1,38 @@
// SiYuan - Build Your Eternal Digital Garden
// Copyright (c) 2020-present, b3log.org
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package api
import (
"net/http"
"github.com/88250/gulu"
"github.com/gin-gonic/gin"
"github.com/siyuan-note/siyuan/kernel/util"
)
func chatGPT(c *gin.Context) {
ret := gulu.Ret.NewResult()
defer c.JSON(http.StatusOK, ret)
arg, ok := util.JsonArg(c, ret)
if !ok {
return
}
msg := arg["msg"].(string)
ret.Data = util.ChatGPT(msg)
}

View file

@ -327,4 +327,6 @@ func ServeAPI(ginServer *gin.Engine) {
ginServer.Handle("GET", "/snippets/*filepath", serveSnippets)
ginServer.Handle("POST", "/api/av/renderAttributeView", model.CheckAuth, renderAttributeView)
ginServer.Handle("POST", "/api/ai/chatGPT", model.CheckAuth, chatGPT)
}

View file

@ -40,6 +40,7 @@ require (
github.com/panjf2000/ants/v2 v2.7.1
github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/radovskyb/watcher v1.0.7
github.com/sashabaranov/go-gpt3 v1.3.3
github.com/shirou/gopsutil/v3 v3.23.1
github.com/siyuan-note/dejavu v0.0.0-20230223101417-691d54268764
github.com/siyuan-note/encryption v0.0.0-20220713091850-5ecd92177b75

View file

@ -266,6 +266,8 @@ github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUA
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 h1:OkMGxebDjyw0ULyrTYWeN0UNCCkmCWfjPnIA2W6oviI=
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06/go.mod h1:+ePHsJ1keEjQtpvf9HHw0f4ZeJ0TLRsxhunSI2hYJSs=
github.com/sashabaranov/go-gpt3 v1.3.3 h1:S8Zd4YybnBaNMK+w+XGGWgsjQY1R+6QE2n9SLzVna9k=
github.com/sashabaranov/go-gpt3 v1.3.3/go.mod h1:BIZdbwdzxZbCrcKGMGH6u2eyGe1xFuX9Anmh3tCP8lQ=
github.com/scylladb/termtables v0.0.0-20191203121021-c4c0b6d42ff4/go.mod h1:C1a7PQSMz9NShzorzCiG2fk9+xuCgLkPeCvMHYR2OWg=
github.com/shirou/gopsutil/v3 v3.23.1 h1:a9KKO+kGLKEvcPIs4W62v0nu3sciVDOOOPUD0Hz7z/4=
github.com/shirou/gopsutil/v3 v3.23.1/go.mod h1:NN6mnm5/0k8jw4cBfCnJtr5L7ErOTg18tMNpgFkn0hA=

111
kernel/util/openai.go Normal file
View file

@ -0,0 +1,111 @@
// SiYuan - Build Your Eternal Digital Garden
// Copyright (c) 2020-present, b3log.org
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package util
import (
"context"
"net/http"
"net/url"
"os"
"strconv"
"strings"
"time"
gogpt "github.com/sashabaranov/go-gpt3"
"github.com/siyuan-note/logging"
)
var (
OpenAIAPIKey = ""
OpenAIAPITimeout = 15 * time.Second
OpenAIAPIProxy = ""
OpenAIAPIMaxTokens = 4096
)
func ChatGPT(msg string) (ret string) {
if "" == OpenAIAPIKey {
return
}
config := gogpt.DefaultConfig(OpenAIAPIKey)
if "" != OpenAIAPIProxy {
proxyUrl, err := url.Parse(OpenAIAPIProxy)
if nil != err {
logging.LogErrorf("OpenAI API proxy error: %v", err)
} else {
config.HTTPClient = &http.Client{Transport: &http.Transport{Proxy: http.ProxyURL(proxyUrl)}}
}
}
c := gogpt.NewClientWithConfig(config)
ctx, cancel := context.WithTimeout(context.Background(), OpenAIAPITimeout)
defer cancel()
req := gogpt.ChatCompletionRequest{
Model: gogpt.GPT3Dot5Turbo,
MaxTokens: OpenAIAPIMaxTokens,
Messages: []gogpt.ChatCompletionMessage{
{
Role: "user",
Content: msg,
},
},
}
resp, err := c.CreateChatCompletion(ctx, req)
if nil != err {
logging.LogErrorf("create chat completion failed: %s", err)
return
}
if 0 < len(resp.Choices) {
ret = resp.Choices[0].Message.Content
ret = strings.TrimSpace(ret)
}
return
}
func initOpenAI() {
OpenAIAPIKey = os.Getenv("SIYUAN_OPENAI_API_KEY")
if "" == OpenAIAPIKey {
return
}
timeout := os.Getenv("SIYUAN_OPENAI_API_TIMEOUT")
if "" != timeout {
timeoutInt, err := strconv.Atoi(timeout)
if nil == err {
OpenAIAPITimeout = time.Duration(timeoutInt) * time.Second
}
}
proxy := os.Getenv("SIYUAN_OPENAI_API_PROXY")
if "" != proxy {
OpenAIAPIProxy = proxy
}
maxTokens := os.Getenv("SIYUAN_OPENAI_API_MAX_TOKENS")
if "" != maxTokens {
maxTokensInt, err := strconv.Atoi(maxTokens)
if nil == err {
OpenAIAPIMaxTokens = maxTokensInt
}
}
if 1 > OpenAIAPIMaxTokens {
OpenAIAPIMaxTokens = 4096
}
logging.LogInfof("OpenAI API enabled [maxTokens=%d, timeout=%ds, proxy=%s]", OpenAIAPIMaxTokens, int(OpenAIAPITimeout.Seconds()), OpenAIAPIProxy)
}

View file

@ -118,6 +118,8 @@ func Boot() {
bootBanner := figure.NewColorFigure("SiYuan", "isometric3", "green", true)
logging.LogInfof("\n" + bootBanner.String())
logBootInfo()
initOpenAI()
}
func setBootDetails(details string) {