mirror of
				https://github.com/yangjian102621/geekai.git
				synced 2025-11-04 08:13:43 +08:00 
			
		
		
		
	handle the exception for web front page
This commit is contained in:
		@@ -9,6 +9,10 @@ package chatimpl
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"bytes"
 | 
						"bytes"
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
	"geekai/core"
 | 
						"geekai/core"
 | 
				
			||||||
	"geekai/core/types"
 | 
						"geekai/core/types"
 | 
				
			||||||
	"geekai/handler"
 | 
						"geekai/handler"
 | 
				
			||||||
@@ -19,10 +23,6 @@ import (
 | 
				
			|||||||
	"geekai/store/vo"
 | 
						"geekai/store/vo"
 | 
				
			||||||
	"geekai/utils"
 | 
						"geekai/utils"
 | 
				
			||||||
	"geekai/utils/resp"
 | 
						"geekai/utils/resp"
 | 
				
			||||||
	"context"
 | 
					 | 
				
			||||||
	"encoding/json"
 | 
					 | 
				
			||||||
	"errors"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
	"net/url"
 | 
						"net/url"
 | 
				
			||||||
	"regexp"
 | 
						"regexp"
 | 
				
			||||||
@@ -481,11 +481,11 @@ func (h *ChatHandler) StopGenerate(c *gin.Context) {
 | 
				
			|||||||
func (h *ChatHandler) doRequest(ctx context.Context, req types.ApiRequest, session *types.ChatSession, apiKey *model.ApiKey) (*http.Response, error) {
 | 
					func (h *ChatHandler) doRequest(ctx context.Context, req types.ApiRequest, session *types.ChatSession, apiKey *model.ApiKey) (*http.Response, error) {
 | 
				
			||||||
	// if the chat model bind a KEY, use it directly
 | 
						// if the chat model bind a KEY, use it directly
 | 
				
			||||||
	if session.Model.KeyId > 0 {
 | 
						if session.Model.KeyId > 0 {
 | 
				
			||||||
		h.DB.Debug().Where("id", session.Model.KeyId).Find(apiKey)
 | 
							h.DB.Debug().Where("id", session.Model.KeyId).Where("enabled", true).Find(apiKey)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// use the last unused key
 | 
						// use the last unused key
 | 
				
			||||||
	if apiKey.Id == 0 {
 | 
						if apiKey.Id == 0 {
 | 
				
			||||||
		h.DB.Debug().Where("platform = ?", session.Model.Platform).Where("type = ?", "chat").Where("enabled = ?", true).Order("last_used_at ASC").First(apiKey)
 | 
							h.DB.Debug().Where("platform", session.Model.Platform).Where("type", "chat").Where("enabled", true).Order("last_used_at ASC").First(apiKey)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if apiKey.Id == 0 {
 | 
						if apiKey.Id == 0 {
 | 
				
			||||||
		return nil, errors.New("no available key, please import key")
 | 
							return nil, errors.New("no available key, please import key")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,13 +9,13 @@ package chatimpl
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"bufio"
 | 
						"bufio"
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
	"geekai/core/types"
 | 
						"geekai/core/types"
 | 
				
			||||||
	"geekai/store/model"
 | 
						"geekai/store/model"
 | 
				
			||||||
	"geekai/store/vo"
 | 
						"geekai/store/vo"
 | 
				
			||||||
	"geekai/utils"
 | 
						"geekai/utils"
 | 
				
			||||||
	"context"
 | 
					 | 
				
			||||||
	"encoding/json"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"html/template"
 | 
						"html/template"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
@@ -75,12 +75,16 @@ func (h *ChatHandler) sendOpenAiMessage(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			var responseBody = types.ApiResponse{}
 | 
								var responseBody = types.ApiResponse{}
 | 
				
			||||||
			err = json.Unmarshal([]byte(line[6:]), &responseBody)
 | 
								err = json.Unmarshal([]byte(line[6:]), &responseBody)
 | 
				
			||||||
			if err != nil || len(responseBody.Choices) == 0 { // 数据解析出错
 | 
								if err != nil { // 数据解析出错
 | 
				
			||||||
				logger.Error(err, line)
 | 
									logger.Error(err, line)
 | 
				
			||||||
				utils.ReplyMessage(ws, ErrorMsg)
 | 
									utils.ReplyMessage(ws, ErrorMsg)
 | 
				
			||||||
				utils.ReplyMessage(ws, ErrImg)
 | 
									utils.ReplyMessage(ws, ErrImg)
 | 
				
			||||||
				break
 | 
									break
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								if len(responseBody.Choices) == 0 { // Fixed: 兼容 Azure API 第一个输出空行
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								
 | 
				
			||||||
			if responseBody.Choices[0].FinishReason == "stop" && len(contents) == 0 {
 | 
								if responseBody.Choices[0].FinishReason == "stop" && len(contents) == 0 {
 | 
				
			||||||
				utils.ReplyMessage(ws, "抱歉😔😔😔,AI助手由于未知原因已经停止输出内容。")
 | 
									utils.ReplyMessage(ws, "抱歉😔😔😔,AI助手由于未知原因已经停止输出内容。")
 | 
				
			||||||
				break
 | 
									break
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,16 +8,16 @@ package chatimpl
 | 
				
			|||||||
// * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 | 
					// * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"geekai/core/types"
 | 
					 | 
				
			||||||
	"geekai/store/model"
 | 
					 | 
				
			||||||
	"geekai/store/vo"
 | 
					 | 
				
			||||||
	"geekai/utils"
 | 
					 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"crypto/hmac"
 | 
						"crypto/hmac"
 | 
				
			||||||
	"crypto/sha256"
 | 
						"crypto/sha256"
 | 
				
			||||||
	"encoding/base64"
 | 
						"encoding/base64"
 | 
				
			||||||
	"encoding/json"
 | 
						"encoding/json"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"geekai/core/types"
 | 
				
			||||||
 | 
						"geekai/store/model"
 | 
				
			||||||
 | 
						"geekai/store/vo"
 | 
				
			||||||
 | 
						"geekai/utils"
 | 
				
			||||||
	"github.com/gorilla/websocket"
 | 
						"github.com/gorilla/websocket"
 | 
				
			||||||
	"gorm.io/gorm"
 | 
						"gorm.io/gorm"
 | 
				
			||||||
	"html/template"
 | 
						"html/template"
 | 
				
			||||||
@@ -80,11 +80,11 @@ func (h *ChatHandler) sendXunFeiMessage(
 | 
				
			|||||||
	var res *gorm.DB
 | 
						var res *gorm.DB
 | 
				
			||||||
	// use the bind key
 | 
						// use the bind key
 | 
				
			||||||
	if session.Model.KeyId > 0 {
 | 
						if session.Model.KeyId > 0 {
 | 
				
			||||||
		res = h.DB.Where("id", session.Model.KeyId).Find(&apiKey)
 | 
							res = h.DB.Where("id", session.Model.KeyId).Where("enabled", true).Find(&apiKey)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// use the last unused key
 | 
						// use the last unused key
 | 
				
			||||||
	if res.Error != nil {
 | 
						if res.Error != nil {
 | 
				
			||||||
		res = h.DB.Where("platform = ?", session.Model.Platform).Where("type = ?", "chat").Where("enabled = ?", true).Order("last_used_at ASC").First(&apiKey)
 | 
							res = h.DB.Where("platform", session.Model.Platform).Where("type", "chat").Where("enabled", true).Order("last_used_at ASC").First(&apiKey)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if res.Error != nil {
 | 
						if res.Error != nil {
 | 
				
			||||||
		utils.ReplyMessage(ws, "抱歉😔😔😔,系统已经没有可用的 API KEY,请联系管理员!")
 | 
							utils.ReplyMessage(ws, "抱歉😔😔😔,系统已经没有可用的 API KEY,请联系管理员!")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,13 +10,13 @@ package handler
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"bufio"
 | 
						"bufio"
 | 
				
			||||||
	"bytes"
 | 
						"bytes"
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
	"geekai/core"
 | 
						"geekai/core"
 | 
				
			||||||
	"geekai/core/types"
 | 
						"geekai/core/types"
 | 
				
			||||||
	"geekai/store/model"
 | 
						"geekai/store/model"
 | 
				
			||||||
	"geekai/utils"
 | 
						"geekai/utils"
 | 
				
			||||||
	"encoding/json"
 | 
					 | 
				
			||||||
	"errors"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"github.com/gin-gonic/gin"
 | 
						"github.com/gin-gonic/gin"
 | 
				
			||||||
	"github.com/gorilla/websocket"
 | 
						"github.com/gorilla/websocket"
 | 
				
			||||||
	"gorm.io/gorm"
 | 
						"gorm.io/gorm"
 | 
				
			||||||
@@ -213,7 +213,7 @@ func (h *MarkMapHandler) doRequest(req types.ApiRequest, chatModel model.ChatMod
 | 
				
			|||||||
	// if the chat model bind a KEY, use it directly
 | 
						// if the chat model bind a KEY, use it directly
 | 
				
			||||||
	var res *gorm.DB
 | 
						var res *gorm.DB
 | 
				
			||||||
	if chatModel.KeyId > 0 {
 | 
						if chatModel.KeyId > 0 {
 | 
				
			||||||
		res = h.DB.Where("id", chatModel.KeyId).Find(apiKey)
 | 
							res = h.DB.Where("id", chatModel.KeyId).Where("enabled", true).Find(apiKey)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// use the last unused key
 | 
						// use the last unused key
 | 
				
			||||||
	if apiKey.Id == 0 {
 | 
						if apiKey.Id == 0 {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -57,6 +57,7 @@ export default defineComponent({
 | 
				
			|||||||
    if (!this.finalTokens) {
 | 
					    if (!this.finalTokens) {
 | 
				
			||||||
      httpPost("/api/chat/tokens", {text: this.content, model: this.model}).then(res => {
 | 
					      httpPost("/api/chat/tokens", {text: this.content, model: this.model}).then(res => {
 | 
				
			||||||
        this.finalTokens = res.data;
 | 
					        this.finalTokens = res.data;
 | 
				
			||||||
 | 
					      }).catch(() => {
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -654,55 +654,63 @@ const connect = function (chat_id, role_id) {
 | 
				
			|||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _socket.addEventListener('message', event => {
 | 
					  _socket.addEventListener('message', event => {
 | 
				
			||||||
    if (event.data instanceof Blob) {
 | 
					    try {
 | 
				
			||||||
      const reader = new FileReader();
 | 
					      if (event.data instanceof Blob) {
 | 
				
			||||||
      reader.readAsText(event.data, "UTF-8");
 | 
					        const reader = new FileReader();
 | 
				
			||||||
      reader.onload = () => {
 | 
					        reader.readAsText(event.data, "UTF-8");
 | 
				
			||||||
        const data = JSON.parse(String(reader.result));
 | 
					        reader.onload = () => {
 | 
				
			||||||
        if (data.type === 'start') {
 | 
					          const data = JSON.parse(String(reader.result));
 | 
				
			||||||
          console.log(data)
 | 
					          if (data.type === 'start') {
 | 
				
			||||||
          chatData.value.push({
 | 
					            chatData.value.push({
 | 
				
			||||||
            type: "reply",
 | 
					              type: "reply",
 | 
				
			||||||
            id: randString(32),
 | 
					              id: randString(32),
 | 
				
			||||||
            icon: _role['icon'],
 | 
					              icon: _role['icon'],
 | 
				
			||||||
            content: ""
 | 
					              content: ""
 | 
				
			||||||
          });
 | 
					            });
 | 
				
			||||||
        } else if (data.type === 'end') { // 消息接收完毕
 | 
					          } else if (data.type === 'end') { // 消息接收完毕
 | 
				
			||||||
          // 追加当前会话到会话列表
 | 
					            // 追加当前会话到会话列表
 | 
				
			||||||
          if (isNewChat && newChatItem.value !== null) {
 | 
					            if (isNewChat && newChatItem.value !== null) {
 | 
				
			||||||
            newChatItem.value['title'] = previousText.value;
 | 
					              newChatItem.value['title'] = previousText.value;
 | 
				
			||||||
            newChatItem.value['chat_id'] = chat_id;
 | 
					              newChatItem.value['chat_id'] = chat_id;
 | 
				
			||||||
            chatList.value.unshift(newChatItem.value);
 | 
					              chatList.value.unshift(newChatItem.value);
 | 
				
			||||||
            activeChat.value = newChatItem.value;
 | 
					              activeChat.value = newChatItem.value;
 | 
				
			||||||
            newChatItem.value = null; // 只追加一次
 | 
					              newChatItem.value = null; // 只追加一次
 | 
				
			||||||
          }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          enableInput()
 | 
					            enableInput()
 | 
				
			||||||
          lineBuffer.value = ''; // 清空缓冲
 | 
					            lineBuffer.value = ''; // 清空缓冲
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          // 获取 token
 | 
					            // 获取 token
 | 
				
			||||||
          const reply = chatData.value[chatData.value.length - 1]
 | 
					            const reply = chatData.value[chatData.value.length - 1]
 | 
				
			||||||
          httpPost("/api/chat/tokens", {text: "", model: getModelValue(modelID.value), chat_id: chat_id}).then(res => {
 | 
					            httpPost("/api/chat/tokens", {
 | 
				
			||||||
            reply['created_at'] = new Date().getTime();
 | 
					              text: "",
 | 
				
			||||||
            reply['tokens'] = res.data;
 | 
					              model: getModelValue(modelID.value),
 | 
				
			||||||
            // 将聊天框的滚动条滑动到最底部
 | 
					              chat_id: chat_id
 | 
				
			||||||
            nextTick(() => {
 | 
					            }).then(res => {
 | 
				
			||||||
              document.getElementById('chat-box').scrollTo(0, document.getElementById('chat-box').scrollHeight)
 | 
					              reply['created_at'] = new Date().getTime();
 | 
				
			||||||
 | 
					              reply['tokens'] = res.data;
 | 
				
			||||||
 | 
					              // 将聊天框的滚动条滑动到最底部
 | 
				
			||||||
 | 
					              nextTick(() => {
 | 
				
			||||||
 | 
					                document.getElementById('chat-box').scrollTo(0, document.getElementById('chat-box').scrollHeight)
 | 
				
			||||||
 | 
					              })
 | 
				
			||||||
 | 
					            }).catch(() => {
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
          })
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        } else {
 | 
					          } else {
 | 
				
			||||||
          lineBuffer.value += data.content;
 | 
					            lineBuffer.value += data.content;
 | 
				
			||||||
          const reply = chatData.value[chatData.value.length - 1]
 | 
					            const reply = chatData.value[chatData.value.length - 1]
 | 
				
			||||||
          reply['orgContent'] = lineBuffer.value;
 | 
					            reply['orgContent'] = lineBuffer.value;
 | 
				
			||||||
          reply['content'] = md.render(processContent(lineBuffer.value));
 | 
					            reply['content'] = md.render(processContent(lineBuffer.value));
 | 
				
			||||||
        }
 | 
					          }
 | 
				
			||||||
        // 将聊天框的滚动条滑动到最底部
 | 
					          // 将聊天框的滚动条滑动到最底部
 | 
				
			||||||
        nextTick(() => {
 | 
					          nextTick(() => {
 | 
				
			||||||
          document.getElementById('chat-box').scrollTo(0, document.getElementById('chat-box').scrollHeight)
 | 
					            document.getElementById('chat-box').scrollTo(0, document.getElementById('chat-box').scrollHeight)
 | 
				
			||||||
          localStorage.setItem("chat_id", chat_id)
 | 
					            localStorage.setItem("chat_id", chat_id)
 | 
				
			||||||
        })
 | 
					          })
 | 
				
			||||||
      };
 | 
					        };
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    } catch (e) {
 | 
				
			||||||
 | 
					      console.error(e)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -99,7 +99,6 @@
 | 
				
			|||||||
import LoginDialog from "@/components/LoginDialog.vue";
 | 
					import LoginDialog from "@/components/LoginDialog.vue";
 | 
				
			||||||
import {nextTick, onMounted, onUnmounted, ref} from 'vue';
 | 
					import {nextTick, onMounted, onUnmounted, ref} from 'vue';
 | 
				
			||||||
import {Markmap} from 'markmap-view';
 | 
					import {Markmap} from 'markmap-view';
 | 
				
			||||||
import {loadCSS, loadJS} from 'markmap-common';
 | 
					 | 
				
			||||||
import {Transformer} from 'markmap-lib';
 | 
					import {Transformer} from 'markmap-lib';
 | 
				
			||||||
import {checkSession} from "@/action/session";
 | 
					import {checkSession} from "@/action/session";
 | 
				
			||||||
import {httpGet} from "@/utils/http";
 | 
					import {httpGet} from "@/utils/http";
 | 
				
			||||||
@@ -129,9 +128,6 @@ const showLoginDialog = ref(false)
 | 
				
			|||||||
const isLogin = ref(false)
 | 
					const isLogin = ref(false)
 | 
				
			||||||
const loginUser = ref({power: 0})
 | 
					const loginUser = ref({power: 0})
 | 
				
			||||||
const transformer = new Transformer();
 | 
					const transformer = new Transformer();
 | 
				
			||||||
const {scripts, styles} = transformer.getAssets()
 | 
					 | 
				
			||||||
loadCSS(styles);
 | 
					 | 
				
			||||||
loadJS(scripts);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const svgRef = ref(null)
 | 
					const svgRef = ref(null)
 | 
				
			||||||
@@ -142,8 +138,12 @@ const loading = ref(false)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
onMounted(() => {
 | 
					onMounted(() => {
 | 
				
			||||||
  initData()
 | 
					  initData()
 | 
				
			||||||
  markMap.value = Markmap.create(svgRef.value)
 | 
					  try {
 | 
				
			||||||
  update()
 | 
					    markMap.value = Markmap.create(svgRef.value)
 | 
				
			||||||
 | 
					    update()
 | 
				
			||||||
 | 
					  } catch (e) {
 | 
				
			||||||
 | 
					    console.error(e)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const initData = () => {
 | 
					const initData = () => {
 | 
				
			||||||
@@ -168,9 +168,13 @@ const initData = () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const update = () => {
 | 
					const update = () => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const {root} = transformer.transform(processContent(text.value))
 | 
					  try {
 | 
				
			||||||
  markMap.value.setData(root)
 | 
					    const {root} = transformer.transform(processContent(text.value))
 | 
				
			||||||
  markMap.value.fit()
 | 
					    markMap.value.setData(root)
 | 
				
			||||||
 | 
					    markMap.value.fit()
 | 
				
			||||||
 | 
					  } catch (e) {
 | 
				
			||||||
 | 
					    console.error(e)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const processContent = (text) => {
 | 
					const processContent = (text) => {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user