user can select function tools by themself

This commit is contained in:
RockYang 2024-09-04 14:53:21 +08:00
parent 1350f388f0
commit 67d83041d7
6 changed files with 116 additions and 36 deletions

View File

@ -57,6 +57,7 @@ type ChatSession struct {
ClientIP string `json:"client_ip"` // 客户端 IP ClientIP string `json:"client_ip"` // 客户端 IP
ChatId string `json:"chat_id"` // 客户端聊天会话 ID, 多会话模式专用字段 ChatId string `json:"chat_id"` // 客户端聊天会话 ID, 多会话模式专用字段
Model ChatModel `json:"model"` // GPT 模型 Model ChatModel `json:"model"` // GPT 模型
Tools string `json:"tools"` // 函数
} }
type ChatModel struct { type ChatModel struct {

View File

@ -73,6 +73,7 @@ func (h *ChatHandler) ChatHandle(c *gin.Context) {
roleId := h.GetInt(c, "role_id", 0) roleId := h.GetInt(c, "role_id", 0)
chatId := c.Query("chat_id") chatId := c.Query("chat_id")
modelId := h.GetInt(c, "model_id", 0) modelId := h.GetInt(c, "model_id", 0)
tools := c.Query("tools")
client := types.NewWsClient(ws) client := types.NewWsClient(ws)
var chatRole model.ChatRole var chatRole model.ChatRole
@ -99,6 +100,7 @@ func (h *ChatHandler) ChatHandle(c *gin.Context) {
SessionId: sessionId, SessionId: sessionId,
ClientIP: c.ClientIP(), ClientIP: c.ClientIP(),
UserId: h.GetLoginUserId(c), UserId: h.GetLoginUserId(c),
Tools: tools,
} }
// use old chat data override the chat model and role ID // use old chat data override the chat model and role ID
@ -211,9 +213,11 @@ func (h *ChatHandler) sendMessage(ctx context.Context, session *types.ChatSessio
} }
req.Temperature = session.Model.Temperature req.Temperature = session.Model.Temperature
req.MaxTokens = session.Model.MaxTokens req.MaxTokens = session.Model.MaxTokens
// OpenAI 支持函数功能
if session.Tools != "" {
toolIds := strings.Split(session.Tools, ",")
var items []model.Function var items []model.Function
res = h.DB.Where("enabled", true).Find(&items) res = h.DB.Where("enabled", true).Where("id IN ?", toolIds).Find(&items)
if res.Error == nil { if res.Error == nil {
var tools = make([]types.Tool, 0) var tools = make([]types.Tool, 0)
for _, v := range items { for _, v := range items {
@ -241,6 +245,7 @@ func (h *ChatHandler) sendMessage(ctx context.Context, session *types.ChatSessio
req.ToolChoice = "auto" req.ToolChoice = "auto"
} }
} }
}
// 加载聊天上下文 // 加载聊天上下文
chatCtx := make([]types.Message, 0) chatCtx := make([]types.Message, 0)

View File

@ -8,15 +8,16 @@ package handler
// * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
import ( import (
"errors"
"fmt"
"geekai/core" "geekai/core"
"geekai/core/types" "geekai/core/types"
"geekai/service/dalle" "geekai/service/dalle"
"geekai/service/oss" "geekai/service/oss"
"geekai/store/model" "geekai/store/model"
"geekai/store/vo"
"geekai/utils" "geekai/utils"
"geekai/utils/resp" "geekai/utils/resp"
"errors"
"fmt"
"strings" "strings"
"time" "time"
@ -224,3 +225,27 @@ func (h *FunctionHandler) Dall3(c *gin.Context) {
resp.SUCCESS(c, content) resp.SUCCESS(c, content)
} }
// List 获取所有的工具函数列表
func (h *FunctionHandler) List(c *gin.Context) {
var items []model.Function
err := h.DB.Where("enabled", true).Find(&items).Error
if err != nil {
resp.ERROR(c, err.Error())
return
}
tools := make([]vo.Function, 0)
for _, v := range items {
var f vo.Function
err = utils.CopyObject(v, &f)
if err != nil {
continue
}
f.Action = ""
f.Token = ""
tools = append(tools, f)
}
resp.SUCCESS(c, tools)
}

View File

@ -433,6 +433,7 @@ func main() {
group.POST("weibo", h.WeiBo) group.POST("weibo", h.WeiBo)
group.POST("zaobao", h.ZaoBao) group.POST("zaobao", h.ZaoBao)
group.POST("dalle3", h.Dall3) group.POST("dalle3", h.Dall3)
group.GET("list", h.List)
}), }),
fx.Invoke(func(s *core.AppServer, h *admin.ChatHandler) { fx.Invoke(func(s *core.AppServer, h *admin.ChatHandler) {
group := s.Engine.Group("/api/admin/chat/") group := s.Engine.Group("/api/admin/chat/")

View File

@ -428,3 +428,10 @@ $borderColor = #4676d0;
width 360px; width 360px;
} }
} }
.tools-dropdown {
width auto
.el-icon {
margin-left 5px;
}
}

View File

@ -100,6 +100,22 @@
</el-option> </el-option>
</el-select> </el-select>
<el-dropdown :hide-on-click="false">
<span class="setting"><i class="iconfont icon-plugin"></i></span>
<template #dropdown>
<el-dropdown-menu class="tools-dropdown">
<el-checkbox-group v-model="toolSelected">
<el-dropdown-item v-for="item in tools" :key="item.id">
<el-checkbox :value="item.id" :label="item.label" @change="changeTool" />
<el-tooltip :content="item.description" placement="right">
<el-icon><InfoFilled /></el-icon>
</el-tooltip>
</el-dropdown-item>
</el-checkbox-group>
</el-dropdown-menu>
</template>
</el-dropdown>
<span class="setting" @click="showChatSetting = true"> <span class="setting" @click="showChatSetting = true">
<el-tooltip class="box-item" effect="dark" content="对话设置"> <el-tooltip class="box-item" effect="dark" content="对话设置">
<i class="iconfont icon-config"></i> <i class="iconfont icon-config"></i>
@ -202,7 +218,7 @@
import {nextTick, onMounted, onUnmounted, ref, watch} from 'vue' import {nextTick, onMounted, onUnmounted, ref, watch} from 'vue'
import ChatPrompt from "@/components/ChatPrompt.vue"; import ChatPrompt from "@/components/ChatPrompt.vue";
import ChatReply from "@/components/ChatReply.vue"; import ChatReply from "@/components/ChatReply.vue";
import {Delete, Edit, More, Plus, Promotion, Search, Share, VideoPause} from '@element-plus/icons-vue' import {Delete, Edit, InfoFilled, More, Plus, Promotion, Search, Share, VideoPause} from '@element-plus/icons-vue'
import 'highlight.js/styles/a11y-dark.css' import 'highlight.js/styles/a11y-dark.css'
import { import {
isMobile, isMobile,
@ -222,6 +238,7 @@ import FileSelect from "@/components/FileSelect.vue";
import FileList from "@/components/FileList.vue"; import FileList from "@/components/FileList.vue";
import ChatSetting from "@/components/ChatSetting.vue"; import ChatSetting from "@/components/ChatSetting.vue";
import BackTop from "@/components/BackTop.vue"; import BackTop from "@/components/BackTop.vue";
import {showMessageError} from "@/utils/dialog";
const title = ref('GeekAI-智能助手'); const title = ref('GeekAI-智能助手');
const models = ref([]) const models = ref([])
@ -253,6 +270,9 @@ const listStyle = ref(store.chatListStyle)
watch(() => store.chatListStyle, (newValue) => { watch(() => store.chatListStyle, (newValue) => {
listStyle.value = newValue listStyle.value = newValue
}); });
const tools = ref([])
const toolSelected = ref([])
const loadHistory = ref(false)
// ChatID // ChatID
chatId.value = router.currentRoute.value.params.id chatId.value = router.currentRoute.value.params.id
@ -294,6 +314,13 @@ httpGet("/api/config/get?key=notice").then(res => {
ElMessage.error("获取系统配置失败:" + e.message) ElMessage.error("获取系统配置失败:" + e.message)
}) })
//
httpGet("/api/function/list").then(res => {
tools.value = res.data
}).catch(e => {
showMessageError("获取工具函数失败:" + e.message)
})
onMounted(() => { onMounted(() => {
resizeElement(); resizeElement();
initData() initData()
@ -464,9 +491,19 @@ const newChat = () => {
}; };
showStopGenerate.value = false; showStopGenerate.value = false;
router.push(`/chat/${chatId.value}`) router.push(`/chat/${chatId.value}`)
loadHistory.value = true
connect() connect()
} }
//
const changeTool = () => {
if (!isLogin.value) {
return;
}
loadHistory.value = false
socket.value.close()
}
// //
const loadChat = function (chat) { const loadChat = function (chat) {
@ -485,6 +522,7 @@ const loadChat = function (chat) {
chatId.value = chat.chat_id; chatId.value = chat.chat_id;
showStopGenerate.value = false; showStopGenerate.value = false;
router.push(`/chat/${chatId.value}`) router.push(`/chat/${chatId.value}`)
loadHistory.value = true
socket.value.close() socket.value.close()
} }
@ -578,10 +616,13 @@ const connect = function () {
} }
loading.value = true loading.value = true
const _socket = new WebSocket(host + `/api/chat/new?session_id=${sessionId.value}&role_id=${roleId.value}&chat_id=${chatId.value}&model_id=${modelID.value}&token=${getUserToken()}`); const toolIds = toolSelected.value.join(',')
const _socket = new WebSocket(host + `/api/chat/new?session_id=${sessionId.value}&role_id=${roleId.value}&chat_id=${chatId.value}&model_id=${modelID.value}&token=${getUserToken()}&tools=${toolIds}`);
_socket.addEventListener('open', () => { _socket.addEventListener('open', () => {
enableInput() enableInput()
if (loadHistory.value) {
loadChatHistory(chatId.value) loadChatHistory(chatId.value)
}
loading.value = false loading.value = false
}); });