Go使用Google?Gemini?Pro?API創(chuàng)建簡單聊天機(jī)器人
gemini go sdk實現(xiàn)命令行聊天機(jī)器人
最近Google 如期發(fā)布Gemini Pro API,目前為免費(fèi)使用,Go的SDK也已經(jīng)在github上發(fā)布了
具體地址見:https://github.com/google/generative-ai-go
本文將通過最新的gemini go sdk來實現(xiàn)命令行聊天機(jī)器人。
Go語言實現(xiàn)監(jiān)聽鍵盤輸入
reader := bufio.NewReader(os.Stdin)
// 讀取輸入直到遇到第一個換行符
input, err := reader.ReadString('\n')reader對象的ReadString方法即可實現(xiàn)我們需要的監(jiān)聽鍵盤的方法,這里設(shè)置為當(dāng)監(jiān)聽到回車輸入的時候,則讀取用戶輸入的內(nèi)容。
整合Gemini SDK
前提條件
確保Go SDK版本為1.20+
去Gemini SDK 后臺(https://makersuite.google.com/app/apikey?hl=zh-cn)申請api key。
安裝SDK
go get github.com/google/generative-ai-go
實例化一個gemini Client
func getGeminiClient() *genai.Client {
ctx := context.Background()
client, err := genai.NewClient(ctx, option.WithAPIKey("YOUR-API-KEY"))
if err != nil {
log.Fatal(err)
}
return client
}根據(jù)用戶輸入向gemini 服務(wù)器發(fā)請求。
func handleChat(ctx context.Context, client *genai.Client, cs *genai.ChatSession, content string) error {
if cs == nil {
return errors.New("chat session is nil")
}
return geminiPro(ctx, cs, content)
}
func geminiPro(ctx context.Context, cs *genai.ChatSession, content string) error {
prompt := genai.Text(content)
iter := cs.SendMessageStream(ctx, prompt)
fmt.Print("[Gemini]:")
for {
resp, err := iter.Next()
if err == iterator.Done {
break
}
if err != nil {
fmt.Print("Something wrong, please try again later. \n")
return err
}
printChatResponse(resp)
}
return nil
}
func printChatResponse(resp *genai.GenerateContentResponse) {
for _, c := range resp.Candidates {
for _, p := range c.Content.Parts {
fmt.Printf("%v", p)
}
}
fmt.Println()
}這里就是整個Gemini SDK調(diào)用的核心代碼了,每次使用ChatSession對象(geminiPro方法中的cs變量)發(fā)送消息,這里使用的的是流式子消息傳輸,所以,在geminiPro方法里面,需要啟動一個for循環(huán),等待消息的全部輸出。
我們整個會話使用的都是同一個ChatSession對象,并且,在發(fā)送消息之后,內(nèi)容會自動加到ChatSession對象的History里面,History也就是歷史會話,Gemini SDK一樣可以根據(jù)上下文來實現(xiàn)問答的實現(xiàn)。
如何實現(xiàn)ChatSession只實例化一次
前面已經(jīng)說過,一個會話需要使用同一個ChatSession對象,我們自然而然就想到Go里面的sync.Once對象,但在使用Gemini Go SDK的過程中發(fā)現(xiàn),經(jīng)常會遇到請求出錯的情況,一旦請求出錯,就需要重新去創(chuàng)建一個會話對象,所以,Go語言提供的sync.Once并不能滿足這個需求,所以,需要自己實現(xiàn)一個可以重置的Once對象,這里命名為ResetOnce對象,代碼如下:
// ResettableOnce 結(jié)構(gòu)體包含一個互斥鎖和一個標(biāo)記是否已執(zhí)行的布爾值
type ResettableOnce struct {
m sync.Mutex
done bool
}
// Do 方法類似于 sync.Once 的 Do,但可以通過調(diào)用 Reset 來重置
func (o *ResettableOnce) Do(f func()) {
o.m.Lock()
defer o.m.Unlock()
if !o.done {
defer func() { o.done = true }()
f()
}
}
// Reset 方法重置 Once,允許再次調(diào)用 Do
func (o *ResettableOnce) Reset() {
o.m.Lock()
defer o.m.Unlock()
o.done = false
}如何實現(xiàn)用戶ChatSession重新創(chuàng)建之后,保持之前的History?
在實際的項目中,我們肯定會對History做持久化,但這里這里,僅使用一個全局的history來模擬持久化。
當(dāng)ChatSession對象被新建之后,需要將全局history的內(nèi)容復(fù)制給新創(chuàng)建的ChatSession對象,這里為了模擬這個過程,在用戶輸入內(nèi)容的時候,添加一個檢測內(nèi)容是否為reset字符串的操作,當(dāng)檢測用戶輸入為reset字符串的時候,則主動新建一個ChatSession,同時將新的ChatSession的History賦值為之前的history內(nèi)容,這樣即使新建立一個ChatSession它還能保持之前的會話記錄。
代碼如下:
func handleReset(client *genai.Client, cs **genai.ChatSession, history *[]*genai.Content) {
fmt.Println("[System]", "Resetting chat session.")
once.Reset()
once.Do(func() {
*cs = startChatSession(client, *history)
})
}
func startChatSession(client *genai.Client, history []*genai.Content) *genai.ChatSession {
model := client.GenerativeModel("gemini-pro")
cs := model.StartChat()
if len(history) > 0 {
cs.History = history
}
return cs
}總結(jié)
如果在實際中使用這個SDK進(jìn)行商業(yè)化開發(fā),那么比如需要處理用戶多會話的管理,其實這個過程也不麻煩,只要維護(hù)好用戶以及它對應(yīng)的history的關(guān)系,在用戶每次開始登錄進(jìn)入系統(tǒng),并且選擇會話的時候,將對應(yīng)的history給設(shè)好即可。但要注意的是,目前pro版本支持的最大的32K的上下文。另外SDK中還提供了gemini-pro-vision模型的使用,你們有興趣的可以自己去探索。
以上就是Go使用Google Gemini Pro API創(chuàng)建簡單聊天機(jī)器人的詳細(xì)內(nèi)容,更多關(guān)于go創(chuàng)建聊天機(jī)器人的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
詳解golang中的結(jié)構(gòu)體編解碼神器Mapstructure庫
mapstructure是GO字典(map[string]interface{})和Go結(jié)構(gòu)體之間轉(zhuǎn)換的編解碼工具,這篇文章主要為大家介紹一下Mapstructure庫的相關(guān)使用,希望對大家有所幫助2023-09-09
Golang使用Docker進(jìn)行集成測試的示例詳解
集成測試需要解決外部依賴問題,如?MySQL、Redis、網(wǎng)絡(luò)等依賴,本文就來聊聊?Go?程序如何使用?Docker?來解決集成測試中外部依賴問題吧2023-07-07
解讀unsafe.Pointer和uintptr的區(qū)別
這篇文章主要介紹了解讀unsafe.Pointer和uintptr的區(qū)別及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-02-02

