diff --git a/api/chat.go b/api/chat.go index 3c95365..666bbfe 100644 --- a/api/chat.go +++ b/api/chat.go @@ -29,6 +29,14 @@ func SendSegmentMessage(conn *websocket.Conn, message types.ChatGPTSegmentRespon _ = conn.WriteMessage(websocket.TextMessage, []byte(utils.ToJson(message))) } +func GetErrorQuota(isGPT4 bool) float32 { + if isGPT4 { + return -0xe // special value for error + } else { + return 0 + } +} + func TextChat(db *sql.DB, cache *redis.Client, user *auth.User, conn *websocket.Conn, instance *conversation.Conversation) string { var keyword string var segment []types.ChatGPTMessage @@ -65,7 +73,7 @@ func TextChat(db *sql.DB, cache *redis.Client, user *auth.User, conn *websocket. } SendSegmentMessage(conn, types.ChatGPTSegmentResponse{ Message: defaultErrorMessage, - Quota: -0xe, // special value for error + Quota: GetErrorQuota(instance.IsEnableGPT4()), End: true, }) return defaultErrorMessage diff --git a/api/utils.go b/api/utils.go index 6a85bce..97dd667 100644 --- a/api/utils.go +++ b/api/utils.go @@ -27,8 +27,6 @@ func ChatWithWeb(message []types.ChatGPTMessage, long bool) (string, []types.Cha Role: "system", Content: fmt.Sprintf("你将扮演AI问答助手,你的知识库不是截止于2021年9月,而是可以实时联网的,你可以提供实时联网的知识库。"+ "网站使用markdown链接包裹,多使用emoji和颜文字,给予用户精确的答复。"+ - "当介绍github的用户的时候,可以使用code stats分析加入到你回答的末尾中,图片格式为 ![User Stats](https://stats.deeptrain.net/user/{username})"+ - "当介绍github的仓库的时候,可以使用code stats分析加入到你回答的末尾中,图片格式为 ![Repo Stats](https://stats.deeptrain.net/repo/{username}/{repo})"+ "当前时间: %s, 实时联网搜索结果:%s", time.Now().Format("2006-01-02 15:04:05"), data, ), @@ -42,7 +40,7 @@ func GetRandomKey(apikey string) string { } func StringCleaner(content string) string { - for _, replacer := range []string{",", "、", ",", "。", ":", ":", ";", ";", "!", "!", "?", "?", "(", ")", "(", ")", "关键字", "空"} { + for _, replacer := range []string{",", "、", ",", "。", ":", ":", ";", ";", "!", "!", "=", "?", "?", "(", ")", "(", ")", "关键字", "空", "1+1"} { content = strings.ReplaceAll(content, replacer, " ") } return strings.TrimSpace(content) diff --git a/app/src/conversation/manager.ts b/app/src/conversation/manager.ts index d419a78..c5afff3 100644 --- a/app/src/conversation/manager.ts +++ b/app/src/conversation/manager.ts @@ -28,7 +28,7 @@ export class Manager { console.debug( `[manager] conversation receive message (id: ${idx}, length: ${message.length})`, ); - this.dispatch(setMessages(message)); + if (idx === this.current) this.dispatch(setMessages(message)); } public getCurrent(): number { diff --git a/app/src/store/chat.ts b/app/src/store/chat.ts index c424a14..cac9af9 100644 --- a/app/src/store/chat.ts +++ b/app/src/store/chat.ts @@ -32,7 +32,10 @@ const chatSlice = createSlice({ }, addHistory: (state, action) => { const name = action.payload.message as string; - const id = Math.max(...state.history.map((item) => item.id)) + 1; + const id = state.history.length ? + Math.max(...state.history.map((item) => item.id)) + 1 + : 1; + state.history = insertStart(state.history, { id, name, message: [] }); state.current = id; action.payload.hook(id); diff --git a/conversation/storage.go b/conversation/storage.go index d88add1..bb69212 100644 --- a/conversation/storage.go +++ b/conversation/storage.go @@ -9,7 +9,7 @@ import ( func (c *Conversation) SaveConversation(db *sql.DB) bool { data := utils.ToJson(c.GetMessage()) - query := "INSERT INTO conversation (user_id, conversation_id, conversation_name, data) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE conversation_name = VALUES(conversation_name), data = VALUES(data)" + query := `INSERT INTO conversation (user_id, conversation_id, conversation_name, data) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE conversation_name = VALUES(conversation_name), data = VALUES(data)` stmt, err := db.Prepare(query) if err != nil { @@ -59,7 +59,7 @@ func LoadConversation(db *sql.DB, userId int64, conversationId int64) *Conversat func LoadConversationList(db *sql.DB, userId int64) []Conversation { var conversationList []Conversation - rows, err := db.Query("SELECT conversation_id, conversation_name FROM conversation WHERE user_id = ?", userId) + rows, err := db.Query("SELECT conversation_id, conversation_name FROM conversation WHERE user_id = ? ORDER BY conversation_id LIMIT 100", userId) if err != nil { return conversationList } diff --git a/go.mod b/go.mod index 6f42afd..3eb3657 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.14.0 // indirect github.com/goccy/go-json v0.10.2 // indirect - github.com/google/uuid v1.3.0 // indirect + github.com/google/uuid v1.3.1 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect diff --git a/go.sum b/go.sum index 0ad7135..7e7f593 100644 --- a/go.sum +++ b/go.sum @@ -151,6 +151,8 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4 github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= diff --git a/utils/char.go b/utils/char.go index 9d1d8b7..cfad5a2 100644 --- a/utils/char.go +++ b/utils/char.go @@ -45,6 +45,15 @@ func Marshal[T interface{}](data T) string { return string(res) } +func MapToStruct[T any](data interface{}) *T { + val := Marshal(data) + if form, err := Unmarshal[T]([]byte(val)); err == nil { + return &form + } else { + return nil + } +} + func ToInt(value string) int { if res, err := strconv.Atoi(value); err == nil { return res diff --git a/web/search.go b/web/search.go index 7783b15..458a390 100644 --- a/web/search.go +++ b/web/search.go @@ -24,6 +24,9 @@ func RequestWithUA(url string) string { func SearchBing(q string) string { uri := GetBingUrl(q) + if res := CallPilotAPI(uri); res != nil { + return utils.Marshal(res.Results) + } data := RequestWithUA(uri) return ParseBing(data) } diff --git a/web/webpilot.go b/web/webpilot.go new file mode 100644 index 0000000..19af71f --- /dev/null +++ b/web/webpilot.go @@ -0,0 +1,36 @@ +package web + +import ( + "chat/utils" + "github.com/google/uuid" +) + +type PilotResponseResult struct { + Title string `json:"title"` + Link string `json:"link"` + Snippet string `json:"snippet"` +} + +type PilotResponse struct { + Results []PilotResponseResult `json:"extra_search_results" required:"true"` +} + +func GenerateFriendUID() string { + return uuid.New().String() +} + +func CallPilotAPI(url string) *PilotResponse { + data, err := utils.Post("https://webreader.webpilotai.com/api/visit-web", map[string]string{ + "Content-Type": "application/json", + "WebPilot-Friend-UID": GenerateFriendUID(), + }, map[string]interface{}{ + "link": url, + "user_has_request": false, + }) + + if err != nil { + return nil + } + + return utils.MapToStruct[PilotResponse](data) +}