1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
| type ZhipuAIBot struct { token string SystemPrompt string messageChain []*Message }
const toolPrompt = `当你想要使用工具时,输出一个 #Call + 工具,没事就不用管 你有以下可用工具: ### 校园集市论坛相关: - 'browse_homepage()':访问主页,获取最新的帖子列表。 - 'browse_hot()':访问24小时内热度最高的帖子列表。 - 'search(keyword:string)':使用关键词搜索相关帖子。 - 'view_post(post_id:string)':查看某篇帖子的详细内容。 - 'view_comments(post_id:string)':查看某篇帖子的评论区内容。
当你要执行某个操作时,请以'#Call' + 严格的 JSON 格式输出你的动作和参数,例如:
#Call { "action": "search", "parameters": { "keyword": "图书馆" } }
注意事项: 1.请确保每次响应只包含一个动作,并且不要添加任何额外解释。我会根据你的指令执行操作并将结果反馈给你。 2.不要连续多次调用#Call,调用几次后就回答问题 3.有些#Call调用在短时间内是不变的,比如热帖,评论,帖子详情,请求过了就不要重复请求了 `
func NewZhipu(token string, prompt string) *ZhipuAIBot { zp := &ZhipuAIBot{ token: token, SystemPrompt: prompt + "\n" + toolPrompt, } zp.messageChain = []*Message{ { Role: "system", Content: zp.SystemPrompt, }, } return zp }
const requestUrl string = "https://open.bigmodel.cn/api/paas/v4/chat/completions"
type RequestBody struct { Model string `json:"model"` Messages []*Message `json:"messages"` Stream bool `json:"stream"` }
type ResponseBody struct { Choices []struct { Index int `json:"index"` Message struct { Content string `json:"content"` } `json:"message"` } `json:"choices"` }
type thinkingResponse struct { thinking string text string }
func request(msg []*Message, token string) *thinkingResponse { client := &http.Client{} body := &RequestBody{ Model: "glm-z1-flash", Messages: msg, Stream: false, } postBytes, err := json.Marshal(body) if err != nil { log.Println(err) } request, err := http.NewRequest(http.MethodPost, requestUrl, bytes.NewReader(postBytes)) request.Header.Set("Content-Type", "application/json") request.Header.Set("Authorization", "Bearer "+token) if err != nil { log.Println(err) return nil } resp, err := client.Do(request) if err != nil { log.Println(err) return nil } defer resp.Body.Close() respBytes, err := io.ReadAll(resp.Body) if err != nil { log.Println(err) return nil } var response ResponseBody json.Unmarshal(respBytes, &response) sort.Slice(response.Choices, func(i, j int) bool { return response.Choices[i].Index < response.Choices[j].Index }) var respText string for _, v := range response.Choices { respText += v.Message.Content } splitText := strings.Split(respText, "</think>") if len(splitText) == 2 { return &thinkingResponse{ thinking: strings.TrimSpace(splitText[0]), text: strings.TrimSpace(splitText[1]), } } else { return nil } }
func (zp *ZhipuAIBot) Ask(question string) *AiAnswer { if strings.HasPrefix(question, "#新对话") { zp.messageChain = []*Message{ { Role: "system", Content: zp.SystemPrompt, }, } } zp.messageChain = append(zp.messageChain, &Message{ Role: "user", Content: question, }) isFunccall := false funcCallNums := 0 funcs := []functioncall.FunctionCall{} resp := request(zp.messageChain, zp.token) if resp == nil { return nil } zp.messageChain = append(zp.messageChain, &Message{ Role: "assistant", Content: resp.text, }) return &AiAnswer{ Response: resp.text, IsFunctionCall: isFunccall, FunctionCall: funcs, } }
|