mirror of
https://github.com/siyuan-note/siyuan.git
synced 2025-05-16 17:10:53 +08:00
Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
commit
5e9f8956ff
@ -6,24 +6,24 @@
|
||||
"20200924095938-a9p5450": 2,
|
||||
"20200924100110-vcg96wy": 1,
|
||||
"20200924100635-ms0p9lb": 6,
|
||||
"20200924100717-yzwzn64": 18,
|
||||
"20200924100717-yzwzn64": 19,
|
||||
"20200924100744-br924ar": 8,
|
||||
"20200924100808-j9sddk9": 2,
|
||||
"20200924100906-0u4zfq3": 4,
|
||||
"20200924100950-9op5xi1": 15,
|
||||
"20200924100950-9op5xi1": 16,
|
||||
"20200924101106-19z4kaa": 1,
|
||||
"20200924101200-gss5vee": 4,
|
||||
"20200924101225-k254i8g": 2,
|
||||
"20200924101256-f8b1sbi": 3,
|
||||
"20201004194026-s8h2cog": 16,
|
||||
"20201004194026-s8h2cog": 17,
|
||||
"20201117112518-dott91x": 6,
|
||||
"20201121224345-rc27qvo": 5,
|
||||
"20201204184532-3qm9l8n": 9,
|
||||
"20201210233038-3xr19g5": 5,
|
||||
"20201222100222-q47d64s": 2,
|
||||
"20201222100339-i5hzcph": 1,
|
||||
"20201227201128-m1wrouw": 17,
|
||||
"20201227201751-gv0fpx2": 19,
|
||||
"20201227201128-m1wrouw": 18,
|
||||
"20201227201751-gv0fpx2": 20,
|
||||
"20210110181011-fbhoesf": 5,
|
||||
"20210117215840-jcl17fx": 3,
|
||||
"20210127203829-qe2mzof": 10,
|
||||
@ -47,6 +47,7 @@
|
||||
"20220708103401-mgydrfg": 3,
|
||||
"20221016204105-qx2aq0g": 3,
|
||||
"20221223221636-ms2b4w9": 14,
|
||||
"20230104152135-1iei0xa": 20,
|
||||
"20230106104821-9nfphwm": 1
|
||||
"20230104152135-1iei0xa": 21,
|
||||
"20230106104821-9nfphwm": 1,
|
||||
"20230304000547-ibldj1z": 15
|
||||
}
|
@ -5,7 +5,7 @@
|
||||
"Properties": {
|
||||
"id": "20230304000547-ibldj1z",
|
||||
"title": "Artificial Intelligence",
|
||||
"updated": "20230304000723"
|
||||
"updated": "20230305102525"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
@ -70,7 +70,7 @@
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20230304000646-a5e7srt",
|
||||
"updated": "20230304000646"
|
||||
"updated": "20230305102525"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
@ -114,7 +114,7 @@
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20230304000646-6207b6r",
|
||||
"updated": "20230304000646"
|
||||
"updated": "20230305102525"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
@ -137,7 +137,7 @@
|
||||
"ListData": {},
|
||||
"Properties": {
|
||||
"id": "20230304000646-aj5szch",
|
||||
"updated": "20230304000646"
|
||||
"updated": "20230305102525"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
@ -186,7 +186,7 @@
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20230304000646-78w2ck5",
|
||||
"updated": "20230304000646"
|
||||
"updated": "20230305102525"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
@ -194,7 +194,7 @@
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20230304000646-2blt9e0",
|
||||
"updated": "20230304000646"
|
||||
"updated": "20230305102525"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
@ -208,7 +208,7 @@
|
||||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": " specifies the timeout time (seconds), the default is 15 seconds (optional)"
|
||||
"Data": " specifies the timeout time (seconds), the default is 30 seconds (optional)"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -260,7 +260,7 @@
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20230304000646-8swnrqn",
|
||||
"updated": "20230304000646"
|
||||
"updated": "20230304171533"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
@ -268,7 +268,7 @@
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20230304000646-33hvl2k",
|
||||
"updated": "20230304000646"
|
||||
"updated": "20230304171533"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
@ -282,7 +282,7 @@
|
||||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": " specifies the number of tokens, the default is 0, that is unlimited (optional)"
|
||||
"Data": " specifies the number of tokens, the default is 0, that is, the default value of the model is used (optional)"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"20200812220555-lj3enxa": 1,
|
||||
"20200813004551-gm0pbn1": 15,
|
||||
"20200813004551-gm0pbn1": 16,
|
||||
"20200813004931-q4cu8na": 1,
|
||||
"20200813013559-sgbzl5k": 3,
|
||||
"20200813093015-u6bopdt": 2,
|
||||
@ -9,20 +9,20 @@
|
||||
"20200813163359-v04n73b": 4,
|
||||
"20200822191536-rm6hwid": 4,
|
||||
"20200825162036-4dx365o": 1,
|
||||
"20200828105441-r76vmu5": 18,
|
||||
"20200828105441-r76vmu5": 19,
|
||||
"20200905090211-2vixtlf": 2,
|
||||
"20200910201551-h4twhas": 6,
|
||||
"20200915214115-42b8zma": 8,
|
||||
"20200922102318-oz84yu3": 2,
|
||||
"20201004184819-nj8ibyg": 16,
|
||||
"20201004184819-nj8ibyg": 17,
|
||||
"20201117101902-2ewjjum": 6,
|
||||
"20201121212605-9td1a62": 5,
|
||||
"20201204181006-7bkppue": 9,
|
||||
"20201210103036-1x3vm8t": 5,
|
||||
"20201222093044-rx4zjoy": 1,
|
||||
"20201222095049-hghafhe": 2,
|
||||
"20201227173504-847cs1q": 17,
|
||||
"20201227194925-7ipoiv6": 19,
|
||||
"20201227173504-847cs1q": 18,
|
||||
"20201227194925-7ipoiv6": 20,
|
||||
"20210110175347-2xrwoiq": 5,
|
||||
"20210117211155-56n4odu": 3,
|
||||
"20210127202655-2334vvv": 10,
|
||||
@ -48,6 +48,7 @@
|
||||
"20220708095345-tu7nz95": 3,
|
||||
"20221016213308-uz5af79": 3,
|
||||
"20221223215557-o6gfsoy": 14,
|
||||
"20230104144904-39br4c6": 20,
|
||||
"20230106101434-e6g4av3": 1
|
||||
"20230104144904-39br4c6": 21,
|
||||
"20230106101434-e6g4av3": 1,
|
||||
"20230303235619-ex5l63e": 15
|
||||
}
|
@ -5,7 +5,7 @@
|
||||
"Properties": {
|
||||
"id": "20230303235619-ex5l63e",
|
||||
"title": "人工智能",
|
||||
"updated": "20230304000753"
|
||||
"updated": "20230305102554"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
@ -70,7 +70,7 @@
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20230303235749-kurfjky",
|
||||
"updated": "20230304000517"
|
||||
"updated": "20230305102554"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
@ -113,7 +113,8 @@
|
||||
"Num": 2
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20230303235819-0o648f9"
|
||||
"id": "20230303235819-0o648f9",
|
||||
"updated": "20230305102554"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
@ -136,7 +137,7 @@
|
||||
"ListData": {},
|
||||
"Properties": {
|
||||
"id": "20230303235950-z00ou0r",
|
||||
"updated": "20230303235950"
|
||||
"updated": "20230305102554"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
@ -185,7 +186,7 @@
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20230303235950-l6o3a5a",
|
||||
"updated": "20230303235950"
|
||||
"updated": "20230305102554"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
@ -193,7 +194,7 @@
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20230303235950-zfhft7e",
|
||||
"updated": "20230303235950"
|
||||
"updated": "20230305102554"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
@ -207,7 +208,7 @@
|
||||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": " 指定超时时间(秒),默认为 15 秒(可选)"
|
||||
"Data": " 指定超时时间(秒),默认为 30 秒(可选)"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -259,7 +260,7 @@
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20230303235950-5y60wvh",
|
||||
"updated": "20230303235950"
|
||||
"updated": "20230304171349"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
@ -267,7 +268,7 @@
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20230303235950-ffevwk8",
|
||||
"updated": "20230303235950"
|
||||
"updated": "20230304171349"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
@ -281,7 +282,11 @@
|
||||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": " 指定 tokens 数量,默认为 0,即不限制(可选)"
|
||||
"Data": " 指定 tokens 数量,默认为 0,即使用模型默认值"
|
||||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": "(可选)"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -18,14 +18,14 @@
|
||||
"20211226121203-rjjngpz": 6,
|
||||
"20211226121232-23s79xr": 7,
|
||||
"20211226121319-emrk2yy": 1,
|
||||
"20211226121329-c5v3dto": 19,
|
||||
"20211226121329-c5v3dto": 20,
|
||||
"20211226121332-irgblss": 4,
|
||||
"20211226121438-xaafdo8": 2,
|
||||
"20211226121503-k3jma6m": 1,
|
||||
"20211226122358-hctqcn5": 18,
|
||||
"20211226122459-08mi5cq": 17,
|
||||
"20211226122523-rl8356a": 16,
|
||||
"20211226122549-jktxego": 15,
|
||||
"20211226122358-hctqcn5": 19,
|
||||
"20211226122459-08mi5cq": 18,
|
||||
"20211226122523-rl8356a": 17,
|
||||
"20211226122549-jktxego": 16,
|
||||
"20211226122707-8cr09co": 13,
|
||||
"20211226122728-cnqf7rz": 12,
|
||||
"20211226122814-r1rdpcx": 11,
|
||||
@ -43,6 +43,7 @@
|
||||
"20220708102441-u6wopo9": 3,
|
||||
"20221016213639-1nag9jj": 3,
|
||||
"20221223221501-mops33i": 14,
|
||||
"20230104151953-48hwkwf": 20,
|
||||
"20230106104645-o838uew": 1
|
||||
"20230104151953-48hwkwf": 21,
|
||||
"20230106104645-o838uew": 1,
|
||||
"20230304000829-9jwu3po": 15
|
||||
}
|
@ -5,7 +5,7 @@
|
||||
"Properties": {
|
||||
"id": "20230304000829-9jwu3po",
|
||||
"title": "人工智能",
|
||||
"updated": "20230304000912"
|
||||
"updated": "20230305102546"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
@ -70,7 +70,7 @@
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20230304000837-t0swnf6",
|
||||
"updated": "20230304000837"
|
||||
"updated": "20230305102546"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
@ -114,7 +114,7 @@
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20230304000837-ktv65zx",
|
||||
"updated": "20230304000837"
|
||||
"updated": "20230305102546"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
@ -137,7 +137,7 @@
|
||||
"ListData": {},
|
||||
"Properties": {
|
||||
"id": "20230304000837-8z180b1",
|
||||
"updated": "20230304000837"
|
||||
"updated": "20230305102546"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
@ -186,7 +186,7 @@
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20230304000837-71slt0q",
|
||||
"updated": "20230304000837"
|
||||
"updated": "20230305102546"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
@ -194,7 +194,7 @@
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20230304000837-t2um8y2",
|
||||
"updated": "20230304000837"
|
||||
"updated": "20230305102546"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
@ -208,7 +208,7 @@
|
||||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": " 指定超時時間(秒),默認為 15 秒(可選)"
|
||||
"Data": " 指定超時時間(秒),默認為 30 秒(可選)"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -260,7 +260,7 @@
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20230304000837-sd6h4qn",
|
||||
"updated": "20230304000837"
|
||||
"updated": "20230304171553"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
@ -268,7 +268,7 @@
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20230304000837-y8kj8ki",
|
||||
"updated": "20230304000837"
|
||||
"updated": "20230304171553"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
@ -282,7 +282,7 @@
|
||||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": " 指定 tokens 數量,默認為 0,即不限制(可選)"
|
||||
"Data": " 指定 tokens 數量,默認為 0,即使用模型默認值(可選)"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -17,11 +17,11 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/siyuan-note/siyuan/kernel/model"
|
||||
"net/http"
|
||||
|
||||
"github.com/88250/gulu"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/siyuan-note/siyuan/kernel/model"
|
||||
"github.com/siyuan-note/siyuan/kernel/util"
|
||||
)
|
||||
|
||||
@ -35,10 +35,57 @@ func chatGPT(c *gin.Context) {
|
||||
}
|
||||
|
||||
msg := arg["msg"].(string)
|
||||
if "" == util.OpenAIAPIKey {
|
||||
util.PushMsg(model.Conf.Language(193), 5000)
|
||||
ret.Data = model.ChatGPT(msg)
|
||||
}
|
||||
|
||||
func chatGPTContinueWriteBlocks(c *gin.Context) {
|
||||
ret := gulu.Ret.NewResult()
|
||||
defer c.JSON(http.StatusOK, ret)
|
||||
|
||||
arg, ok := util.JsonArg(c, ret)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
ret.Data = util.ChatGPT(msg)
|
||||
idsArg := arg["ids"].([]interface{})
|
||||
var ids []string
|
||||
for _, id := range idsArg {
|
||||
ids = append(ids, id.(string))
|
||||
}
|
||||
ret.Data = model.ChatGPTContinueWriteBlocks(ids)
|
||||
}
|
||||
|
||||
func chatGPTTranslate(c *gin.Context) {
|
||||
ret := gulu.Ret.NewResult()
|
||||
defer c.JSON(http.StatusOK, ret)
|
||||
|
||||
arg, ok := util.JsonArg(c, ret)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
idsArg := arg["ids"].([]interface{})
|
||||
var ids []string
|
||||
for _, id := range idsArg {
|
||||
ids = append(ids, id.(string))
|
||||
}
|
||||
lang := arg["lang"].(string)
|
||||
ret.Data = model.ChatGPTTranslate(ids, lang)
|
||||
}
|
||||
|
||||
func chatGPTSummary(c *gin.Context) {
|
||||
ret := gulu.Ret.NewResult()
|
||||
defer c.JSON(http.StatusOK, ret)
|
||||
|
||||
arg, ok := util.JsonArg(c, ret)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
idsArg := arg["ids"].([]interface{})
|
||||
var ids []string
|
||||
for _, id := range idsArg {
|
||||
ids = append(ids, id.(string))
|
||||
}
|
||||
ret.Data = model.ChatGPTSummary(ids)
|
||||
}
|
||||
|
@ -329,4 +329,7 @@ func ServeAPI(ginServer *gin.Engine) {
|
||||
ginServer.Handle("POST", "/api/av/renderAttributeView", model.CheckAuth, renderAttributeView)
|
||||
|
||||
ginServer.Handle("POST", "/api/ai/chatGPT", model.CheckAuth, chatGPT)
|
||||
ginServer.Handle("POST", "/api/ai/chatGPTContinueWriteBlocks", model.CheckAuth, chatGPTContinueWriteBlocks)
|
||||
ginServer.Handle("POST", "/api/ai/chatGPTTranslate", model.CheckAuth, chatGPTTranslate)
|
||||
ginServer.Handle("POST", "/api/ai/chatGPTSummary", model.CheckAuth, chatGPTSummary)
|
||||
}
|
||||
|
@ -198,8 +198,10 @@ func setWorkspaceDir(c *gin.Context) {
|
||||
}
|
||||
|
||||
if gulu.OS.IsWindows() {
|
||||
installDir := filepath.Dir(util.WorkingDir)
|
||||
if strings.HasPrefix(path, installDir) {
|
||||
// 改进判断工作空间路径实现 https://github.com/siyuan-note/siyuan/issues/7569
|
||||
installDirLower := strings.ToLower(filepath.Dir(util.WorkingDir))
|
||||
pathLower := strings.ToLower(path)
|
||||
if strings.HasPrefix(pathLower, installDirLower) && util.IsSubPath(installDirLower, pathLower) {
|
||||
ret.Code = -1
|
||||
ret.Msg = model.Conf.Language(98)
|
||||
ret.Data = map[string]interface{}{"closeTimeout": 5000}
|
||||
|
111
kernel/model/ai.go
Normal file
111
kernel/model/ai.go
Normal 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 model
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/88250/lute/ast"
|
||||
"github.com/88250/lute/parse"
|
||||
"github.com/siyuan-note/siyuan/kernel/treenode"
|
||||
"github.com/siyuan-note/siyuan/kernel/util"
|
||||
)
|
||||
|
||||
func ChatGPTSummary(ids []string) (ret string) {
|
||||
if !isOpenAIAPIEnabled() {
|
||||
return
|
||||
}
|
||||
|
||||
msg := getBlocksContent(ids)
|
||||
ret = util.ChatGPTSummary(msg, Conf.Lang)
|
||||
return
|
||||
}
|
||||
|
||||
func ChatGPTTranslate(ids []string, lang string) (ret string) {
|
||||
if !isOpenAIAPIEnabled() {
|
||||
return
|
||||
}
|
||||
|
||||
msg := getBlocksContent(ids)
|
||||
ret = util.ChatGPTTranslate(msg, lang)
|
||||
return
|
||||
}
|
||||
|
||||
func ChatGPTContinueWriteBlocks(ids []string) (ret string) {
|
||||
if !isOpenAIAPIEnabled() {
|
||||
return
|
||||
}
|
||||
|
||||
msg := getBlocksContent(ids)
|
||||
ret, _ = util.ChatGPTContinueWrite(msg, nil)
|
||||
return
|
||||
}
|
||||
|
||||
func ChatGPT(msg string) (ret string) {
|
||||
if !isOpenAIAPIEnabled() {
|
||||
return
|
||||
}
|
||||
|
||||
return util.ChatGPT(msg)
|
||||
}
|
||||
|
||||
func isOpenAIAPIEnabled() bool {
|
||||
if "" == util.OpenAIAPIKey {
|
||||
util.PushMsg(Conf.Language(193), 5000)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func getBlocksContent(ids []string) string {
|
||||
var nodes []*ast.Node
|
||||
trees := map[string]*parse.Tree{}
|
||||
for _, id := range ids {
|
||||
bt := treenode.GetBlockTree(id)
|
||||
if nil == bt {
|
||||
continue
|
||||
}
|
||||
|
||||
var tree *parse.Tree
|
||||
if tree = trees[bt.RootID]; nil == tree {
|
||||
tree, _ = loadTreeByBlockID(bt.RootID)
|
||||
if nil == tree {
|
||||
continue
|
||||
}
|
||||
|
||||
trees[bt.RootID] = tree
|
||||
}
|
||||
|
||||
if node := treenode.GetNodeInTree(tree, id); nil != node {
|
||||
if ast.NodeDocument == node.Type {
|
||||
for child := node.FirstChild; nil != child; child = child.Next {
|
||||
nodes = append(nodes, child)
|
||||
}
|
||||
} else {
|
||||
nodes = append(nodes, node)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buf := bytes.Buffer{}
|
||||
for _, node := range nodes {
|
||||
content := treenode.NodeStaticContent(node, nil, true)
|
||||
buf.WriteString(content)
|
||||
buf.WriteString("\n\n")
|
||||
}
|
||||
return buf.String()
|
||||
}
|
@ -148,13 +148,13 @@ func FilterFileName(name string) string {
|
||||
return name
|
||||
}
|
||||
|
||||
func IsSubFolder(parent, sub string) bool {
|
||||
if 1 > len(parent) || 1 > len(sub) {
|
||||
func IsSubPath(absPath, toCheckPath string) bool {
|
||||
if 1 > len(absPath) || 1 > len(toCheckPath) {
|
||||
return false
|
||||
}
|
||||
if gulu.OS.IsWindows() {
|
||||
if filepath.IsAbs(parent) && filepath.IsAbs(sub) {
|
||||
if strings.ToLower(parent)[0] != strings.ToLower(sub)[0] {
|
||||
if filepath.IsAbs(absPath) && filepath.IsAbs(toCheckPath) {
|
||||
if strings.ToLower(absPath)[0] != strings.ToLower(toCheckPath)[0] {
|
||||
// 不在一个盘
|
||||
return false
|
||||
}
|
||||
@ -162,7 +162,7 @@ func IsSubFolder(parent, sub string) bool {
|
||||
}
|
||||
|
||||
up := ".." + string(os.PathSeparator)
|
||||
rel, err := filepath.Rel(parent, sub)
|
||||
rel, err := filepath.Rel(absPath, toCheckPath)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
@ -19,9 +19,6 @@ package util
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/88250/lute/html"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
@ -35,12 +32,32 @@ import (
|
||||
|
||||
var (
|
||||
OpenAIAPIKey = ""
|
||||
OpenAIAPITimeout = 15 * time.Second
|
||||
OpenAIAPITimeout = 30 * time.Second
|
||||
OpenAIAPIProxy = ""
|
||||
OpenAIAPIMaxTokens = 0
|
||||
)
|
||||
|
||||
var cachedContextMsg []string
|
||||
|
||||
func ChatGPT(msg string) (ret string) {
|
||||
ret, retCtxMsgs := ChatGPTContinueWrite(msg, cachedContextMsg)
|
||||
cachedContextMsg = append(cachedContextMsg, retCtxMsgs...)
|
||||
return
|
||||
}
|
||||
|
||||
func ChatGPTTranslate(msg string, lang string) (ret string) {
|
||||
msg = "Translate to " + lang + ":\n" + msg
|
||||
ret, _ = ChatGPTContinueWrite(msg, nil)
|
||||
return
|
||||
}
|
||||
|
||||
func ChatGPTSummary(msg string, lang string) (ret string) {
|
||||
msg = "Summarized as follows, the result is in {" + lang + "}:\n" + msg
|
||||
ret, _ = ChatGPTContinueWrite(msg, nil)
|
||||
return
|
||||
}
|
||||
|
||||
func ChatGPTContinueWrite(msg string, contextMsgs []string) (ret string, retContextMsgs []string) {
|
||||
if "" == OpenAIAPIKey {
|
||||
return
|
||||
}
|
||||
@ -48,54 +65,69 @@ func ChatGPT(msg string) (ret string) {
|
||||
PushEndlessProgress("Requesting...")
|
||||
defer ClearPushProgress(100)
|
||||
|
||||
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 := newOpenAIClient()
|
||||
buf := &bytes.Buffer{}
|
||||
for i := 0; i < 7; i++ {
|
||||
part, stop := chatGPT(msg, contextMsgs, c)
|
||||
buf.WriteString(part)
|
||||
|
||||
if stop {
|
||||
break
|
||||
}
|
||||
|
||||
PushEndlessProgress("Continue requesting...")
|
||||
}
|
||||
|
||||
c := gogpt.NewClientWithConfig(config)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), OpenAIAPITimeout)
|
||||
defer cancel()
|
||||
ret = buf.String()
|
||||
ret = strings.TrimSpace(ret)
|
||||
retContextMsgs = append(retContextMsgs, msg, ret)
|
||||
return
|
||||
}
|
||||
|
||||
func chatGPT(msg string, contextMsgs []string, c *gogpt.Client) (ret string, stop bool) {
|
||||
var reqMsgs []gogpt.ChatCompletionMessage
|
||||
if 7 < len(contextMsgs) {
|
||||
contextMsgs = contextMsgs[len(contextMsgs)-7:]
|
||||
}
|
||||
|
||||
for _, ctxMsg := range contextMsgs {
|
||||
reqMsgs = append(reqMsgs, gogpt.ChatCompletionMessage{
|
||||
Role: "user",
|
||||
Content: ctxMsg,
|
||||
})
|
||||
}
|
||||
reqMsgs = append(reqMsgs, gogpt.ChatCompletionMessage{
|
||||
Role: "user",
|
||||
Content: msg,
|
||||
})
|
||||
|
||||
req := gogpt.ChatCompletionRequest{
|
||||
Model: gogpt.GPT3Dot5Turbo,
|
||||
MaxTokens: OpenAIAPIMaxTokens,
|
||||
Messages: []gogpt.ChatCompletionMessage{
|
||||
{
|
||||
Role: "user",
|
||||
Content: msg,
|
||||
},
|
||||
},
|
||||
Messages: reqMsgs,
|
||||
}
|
||||
|
||||
stream, err := c.CreateChatCompletionStream(ctx, req)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), OpenAIAPITimeout)
|
||||
defer cancel()
|
||||
resp, err := c.CreateChatCompletion(ctx, req)
|
||||
if nil != err {
|
||||
logging.LogErrorf("create chat completion stream failed: %s", err)
|
||||
PushErrMsg("Requesting failed, please check kernel log for more details", 3000)
|
||||
logging.LogErrorf("create chat completion failed: %s", err)
|
||||
stop = true
|
||||
return
|
||||
}
|
||||
defer stream.Close()
|
||||
|
||||
buf := bytes.Buffer{}
|
||||
for {
|
||||
resp, recvErr := stream.Recv()
|
||||
if errors.Is(recvErr, io.EOF) {
|
||||
break
|
||||
}
|
||||
if 1 > len(resp.Choices) {
|
||||
stop = true
|
||||
return
|
||||
}
|
||||
|
||||
if nil != recvErr {
|
||||
logging.LogErrorf("create chat completion stream recv failed: %s", recvErr)
|
||||
break
|
||||
}
|
||||
|
||||
for _, choice := range resp.Choices {
|
||||
content := choice.Delta.Content
|
||||
buf.WriteString(content)
|
||||
PushEndlessProgress(html.EscapeHTMLStr(buf.String()))
|
||||
}
|
||||
buf := &strings.Builder{}
|
||||
choice := resp.Choices[0]
|
||||
buf.WriteString(choice.Message.Content)
|
||||
if "length" == choice.FinishReason {
|
||||
stop = false
|
||||
} else {
|
||||
stop = true
|
||||
}
|
||||
|
||||
ret = buf.String()
|
||||
@ -103,6 +135,19 @@ func ChatGPT(msg string) (ret string) {
|
||||
return
|
||||
}
|
||||
|
||||
func newOpenAIClient() *gogpt.Client {
|
||||
config := gogpt.DefaultConfig(OpenAIAPIKey)
|
||||
if "" != OpenAIAPIProxy {
|
||||
proxyUrl, err := url.Parse(OpenAIAPIProxy)
|
||||
if nil != err {
|
||||
logging.LogErrorf("OpenAI API proxy failed: %v", err)
|
||||
} else {
|
||||
config.HTTPClient = &http.Client{Transport: &http.Transport{Proxy: http.ProxyURL(proxyUrl)}}
|
||||
}
|
||||
}
|
||||
return gogpt.NewClientWithConfig(config)
|
||||
}
|
||||
|
||||
func initOpenAI() {
|
||||
OpenAIAPIKey = os.Getenv("SIYUAN_OPENAI_API_KEY")
|
||||
if "" == OpenAIAPIKey {
|
||||
|
Loading…
Reference in New Issue
Block a user