Fix: tool calls

This commit is contained in:
Grail Finder
2024-11-27 15:09:43 +03:00
parent 7f48741b11
commit 55007d27f8
4 changed files with 27 additions and 51 deletions

View File

@@ -34,3 +34,5 @@
- new chat replaces old ones in db; + - new chat replaces old ones in db; +
- empty input to continue bot msg gens new msg index and bot icon; + - empty input to continue bot msg gens new msg index and bot icon; +
- delete last msg: can have unexpected behavior (deletes what appears to be two messages if last bot msg was not generated (should only delete icon in that case)) (should use regen instead of delete in that case); - delete last msg: can have unexpected behavior (deletes what appears to be two messages if last bot msg was not generated (should only delete icon in that case)) (should use regen instead of delete in that case);
- lets say we have two (or more) agents with the same name across multiple chats. These agents go and ask db for topics they memoriesed. Now they can access topics that aren't meant for them. (so memory should have an option: shareble; that indicates if that memory can be shared across chats);
- if option to show sys msg enabled: it show display new tool responses;

24
bot.go
View File

@@ -31,7 +31,7 @@ var (
// TODO: pass as an cli arg or have config // TODO: pass as an cli arg or have config
APIURL = "http://localhost:8080/v1/chat/completions" APIURL = "http://localhost:8080/v1/chat/completions"
logFileName = "log.txt" logFileName = "log.txt"
showSystemMsgs bool showSystemMsgs = true
chunkLimit = 1000 chunkLimit = 1000
activeChatName string activeChatName string
chunkChan = make(chan string, 10) chunkChan = make(chan string, 10)
@@ -158,21 +158,16 @@ out:
} }
func findCall(msg string, tv *tview.TextView) { func findCall(msg string, tv *tview.TextView) {
// prefix := "__tool_call__\n"
// suffix := "\n__tool_call__"
// if !strings.HasPrefix(msg, prefix) ||
// !strings.HasSuffix(msg, suffix) {
// return
// }
// jsStr := strings.TrimSuffix(strings.TrimPrefix(msg, prefix), suffix)
fc := models.FuncCall{} fc := models.FuncCall{}
jsStr := toolCallRE.FindString(msg) jsStr := toolCallRE.FindString(msg)
if jsStr == "" { if jsStr == "" {
// tool call not found
return return
} }
prefix := "__tool_call__\n"
suffix := "\n__tool_call__"
jsStr = strings.TrimSuffix(strings.TrimPrefix(jsStr, prefix), suffix)
if err := json.Unmarshal([]byte(jsStr), &fc); err != nil { if err := json.Unmarshal([]byte(jsStr), &fc); err != nil {
logger.Error("failed to unmarshal tool call", "error", err) logger.Error("failed to unmarshal tool call", "error", err, "json_string", jsStr)
return return
} }
// call a func // call a func
@@ -182,12 +177,9 @@ func findCall(msg string, tv *tview.TextView) {
chatRound(m, toolRole, tv) chatRound(m, toolRole, tv)
return return
} }
resp := f(fc.Args) resp := f(fc.Args...)
toolMsg := fmt.Sprintf("tool response: %+v", resp) toolMsg := fmt.Sprintf("tool response: %+v", string(resp))
// reader := formMsg(chatBody, toolMsg, toolRole)
// sendMsgToLLM()
chatRound(toolMsg, toolRole, tv) chatRound(toolMsg, toolRole, tv)
// return func result to the llm
} }
func chatToTextSlice(showSys bool) []string { func chatToTextSlice(showSys bool) []string {
@@ -248,7 +240,7 @@ func init() {
// load all chats in memory // load all chats in memory
loadHistoryChats() loadHistoryChats()
lastChat := loadOldChatOrGetNew() lastChat := loadOldChatOrGetNew()
logger.Info("loaded history", "chat", lastChat) logger.Info("loaded history")
chatBody = &models.ChatBody{ chatBody = &models.ChatBody{
Model: "modl_name", Model: "modl_name",
Stream: true, Stream: true,

View File

@@ -13,7 +13,7 @@ import (
type FuncCall struct { type FuncCall struct {
Name string `json:"name"` Name string `json:"name"`
Args string `json:"args"` Args []string `json:"args"`
} }
type LLMResp struct { type LLMResp struct {

View File

@@ -2,8 +2,9 @@ package main
import ( import (
"elefant/models" "elefant/models"
"encoding/json" "fmt"
"regexp" "regexp"
"strings"
"time" "time"
) )
@@ -30,7 +31,7 @@ Your current tools:
{ {
"name":"recall_topics", "name":"recall_topics",
"args": null, "args": null,
"when_to_use": "once in a while" "when_to_use": "to see what topics are saved in memory"
} }
] ]
</tools> </tools>
@@ -42,7 +43,8 @@ __tool_call__
"args": "Adam" "args": "Adam"
} }
__tool_call__ __tool_call__
When done right, tool call will be delivered to the 'tool' agent. 'tool' agent will respond with the results of the call. Tool call is addressed to the tool agent, avoid sending more info than tool call itself, while making a call.
When done right, tool call will be delivered to the tool agent. tool agent will respond with the results of the call.
After that you are free to respond to the user. After that you are free to respond to the user.
` `
systemMsg = toolSysMsg systemMsg = toolSysMsg
@@ -61,8 +63,9 @@ also:
func memorise(args ...string) []byte { func memorise(args ...string) []byte {
agent := assistantRole agent := assistantRole
if len(args) < 2 { if len(args) < 2 {
logger.Warn("not enough args to call memorise tool") msg := "not enough args to call memorise tool; need topic and data to remember"
return nil logger.Error(msg)
return []byte(msg)
} }
memory := &models.Memory{ memory := &models.Memory{
Agent: agent, Agent: agent,
@@ -71,7 +74,8 @@ func memorise(args ...string) []byte {
UpdatedAt: time.Now(), UpdatedAt: time.Now(),
} }
store.Memorise(memory) store.Memorise(memory)
return nil msg := fmt.Sprintf("info saved under the topic: %s", args[0])
return []byte(msg)
} }
func recall(args ...string) []byte { func recall(args ...string) []byte {
@@ -82,8 +86,9 @@ func recall(args ...string) []byte {
} }
mind, err := store.Recall(agent, args[0]) mind, err := store.Recall(agent, args[0])
if err != nil { if err != nil {
logger.Error("failed to use tool", "error", err, "args", args) msg := fmt.Sprintf("failed to recall; error: %v; args: %v", err, args)
return nil logger.Error(msg)
return []byte(msg)
} }
return []byte(mind) return []byte(mind)
} }
@@ -95,38 +100,15 @@ func recallTopics(args ...string) []byte {
logger.Error("failed to use tool", "error", err, "args", args) logger.Error("failed to use tool", "error", err, "args", args)
return nil return nil
} }
data, err := json.Marshal(topics) joinedS := strings.Join(topics, ";")
if err != nil { return []byte(joinedS)
logger.Error("failed to use tool", "error", err, "args", args)
return nil
}
return data
} }
func fullMemoryLoad() {} func fullMemoryLoad() {}
// predifine funcs
func getUserDetails(args ...string) []byte {
// db query
// return DB[id[0]]
m := map[string]any{
"username": "fm11",
"id": 24983,
"reputation": 911,
"balance": 214.73,
}
data, err := json.Marshal(m)
if err != nil {
logger.Error("failed to use tool", "error", err, "args", args)
return nil
}
return data
}
type fnSig func(...string) []byte type fnSig func(...string) []byte
var fnMap = map[string]fnSig{ var fnMap = map[string]fnSig{
"get_id": getUserDetails,
"recall": recall, "recall": recall,
"recall_topics": recallTopics, "recall_topics": recallTopics,
"memorise": memorise, "memorise": memorise,