Enha: parsing llm resp [WIP]
This commit is contained in:
		| @@ -4,6 +4,7 @@ import ( | |||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"golias/broker" | ||||||
| 	"golias/config" | 	"golias/config" | ||||||
| 	"golias/models" | 	"golias/models" | ||||||
| 	"golias/pkg/cache" | 	"golias/pkg/cache" | ||||||
| @@ -26,9 +27,22 @@ var ( | |||||||
| 	SignalChanMap = make(map[string]chan bool) | 	SignalChanMap = make(map[string]chan bool) | ||||||
| 	DoneChanMap   = make(map[string]chan bool) | 	DoneChanMap   = make(map[string]chan bool) | ||||||
| 	// got prompt: control character (\\u0000-\\u001F) found while parsing a string at line 4 column 0 | 	// got prompt: control character (\\u0000-\\u001F) found while parsing a string at line 4 column 0 | ||||||
| 	MimePrompt = `we are playing alias;\nyou are a mime (player who gives a clue of one noun word and number of cards you expect them to open) of the red team (people who would guess by your clue want open the red cards);\nplease return your clue, number of cards to open and what words you mean them to find using that clue in json like:\n{\n\"clue\": \"one-word-noun\",\n\"number\": \"number-from-0-to-9\",\n\"word_I_mean_my_team_to_open\": [\"this\", \"that\", ...]\n}\nthe team who openes all their cards first wins.\nplease return json only.\nunopen Blue cards left: %d;\nunopen Red cards left: %d;\nhere is the game info in json:\n%s` | 	MimePrompt    = `we are playing alias;\nyou are a mime (player who gives a clue of one noun word and number of cards you expect them to open) of the red team (people who would guess by your clue want open the red cards);\nplease return your clue, number of cards to open and what words you mean them to find using that clue in json like:\n{\n\"clue\": \"one-word-noun\",\n\"number\": \"number-from-0-to-9\",\n\"words_I_mean_my_team_to_open\": [\"this\", \"that\", ...]\n}\nthe team who openes all their cards first wins.\nplease return json only.\nunopen Blue cards left: %d;\nunopen Red cards left: %d;\nhere is the game info in json:\n%s` | ||||||
|  | 	GuesserPrompt = `we are playing alias;\nyou are to guess words of the red team (people who would guess by your clue want open the red cards) by given clue and a number of meant guesses;\nplease return your guesses and words that you did not wish to open, but think that they could be also meant by the clue in json like:\n{\n\"guesses\": [\"word1\", \"word2\", ...],\n\"could_be\": [\"this\", \"that\", ...]\n}\nthe team who openes all their cards first wins.\nplease return json only.\nunopen Blue cards left: %d;\nunopen Red cards left: %d;\nhere is the game info in json:\n%s` | ||||||
|  | 	// notifier = | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | type MimeResp struct { | ||||||
|  | 	Clue   string   `json:"clue"` | ||||||
|  | 	Number string   `json:"number"` | ||||||
|  | 	Answer []string `json:"words_I_mean_my_team_to_open"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type GusserResp struct { | ||||||
|  | 	Guesses []string `json:"guesses"` | ||||||
|  | 	CouldBe []string `json:"could_be"` | ||||||
|  | } | ||||||
|  |  | ||||||
| type Bot struct { | type Bot struct { | ||||||
| 	Role    string // gueeser | mime | 	Role    string // gueeser | mime | ||||||
| 	Team    string | 	Team    string | ||||||
| @@ -58,7 +72,8 @@ func (b *Bot) StartBot() { | |||||||
| 			prompt := b.BuildPrompt(room) | 			prompt := b.BuildPrompt(room) | ||||||
| 			b.log.Debug("got prompt", "prompt", prompt) | 			b.log.Debug("got prompt", "prompt", prompt) | ||||||
| 			// call llm | 			// call llm | ||||||
| 			if err := b.CallLLM(prompt); err != nil { | 			llmResp, err := b.CallLLM(prompt) | ||||||
|  | 			if err != nil { | ||||||
| 				b.log.Error("bot loop", "error", err) | 				b.log.Error("bot loop", "error", err) | ||||||
| 				return | 				return | ||||||
| 			} | 			} | ||||||
| @@ -66,6 +81,40 @@ func (b *Bot) StartBot() { | |||||||
| 			// if mime -> give clue | 			// if mime -> give clue | ||||||
| 			// if guesser -> open card (does opening one card prompting new loop?) | 			// if guesser -> open card (does opening one card prompting new loop?) | ||||||
| 			// send notification to sse broker | 			// send notification to sse broker | ||||||
|  | 			switch b.Role { | ||||||
|  | 			case models.UserRoleMime: | ||||||
|  | 				// respMap := make(map[string]any) | ||||||
|  | 				mimeResp := MimeResp{} | ||||||
|  | 				if err := json.Unmarshal(llmResp, &mimeResp); err != nil { | ||||||
|  | 					b.log.Error("failed to unmarshal mime resp", "error", err) | ||||||
|  | 					return | ||||||
|  | 				} | ||||||
|  | 				action := models.Action{ | ||||||
|  | 					Actor:      b.BotName, | ||||||
|  | 					ActorColor: b.Team, | ||||||
|  | 					WordColor:  b.Team, | ||||||
|  | 					Action:     "gave clue", | ||||||
|  | 					Word:       mimeResp.Clue, | ||||||
|  | 					Number:     mimeResp.Number, | ||||||
|  | 				} | ||||||
|  | 				room.ActionHistory = append(room.ActionHistory, action) | ||||||
|  | 				room.MimeDone = true | ||||||
|  | 				// notify(models.NotifyBacklogPrefix+room.ID, clue+num) | ||||||
|  | 			case models.UserRoleGuesser: | ||||||
|  | 				gr := GusserResp{} | ||||||
|  | 				if err := json.Unmarshal(llmResp, &gr); err != nil { | ||||||
|  | 					b.log.Error("failed to unmarshal guesser resp", "error", err) | ||||||
|  | 					return | ||||||
|  | 				} | ||||||
|  | 			default: | ||||||
|  | 				b.log.Error("unexpected role", "role", b.Role) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 			broker.Notifier.Notifier <- broker.NotificationEvent{ | ||||||
|  | 				EventName: "", | ||||||
|  | 				Payload:   "", | ||||||
|  | 			} | ||||||
|  | 		// update room info | ||||||
| 		case <-DoneChanMap[b.BotName]: | 		case <-DoneChanMap[b.BotName]: | ||||||
| 			b.log.Debug("got done signal", "bot-name", b.BotName) | 			b.log.Debug("got done signal", "bot-name", b.BotName) | ||||||
| 			return | 			return | ||||||
| @@ -204,7 +253,7 @@ func (b *Bot) BuildPrompt(room *models.Room) string { | |||||||
| 	return "" | 	return "" | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *Bot) CallLLM(prompt string) error { | func (b *Bot) CallLLM(prompt string) ([]byte, error) { | ||||||
| 	method := "POST" | 	method := "POST" | ||||||
| 	payload := strings.NewReader(fmt.Sprintf(`{ | 	payload := strings.NewReader(fmt.Sprintf(`{ | ||||||
|   "model": "deepseek-chat", |   "model": "deepseek-chat", | ||||||
| @@ -225,7 +274,7 @@ func (b *Bot) CallLLM(prompt string) error { | |||||||
| 	req, err := http.NewRequest(method, b.cfg.LLMConfig.URL, payload) | 	req, err := http.NewRequest(method, b.cfg.LLMConfig.URL, payload) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		b.log.Error("failed to make new request", "error", err, "url", b.cfg.LLMConfig.URL) | 		b.log.Error("failed to make new request", "error", err, "url", b.cfg.LLMConfig.URL) | ||||||
| 		return err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 	req.Header.Add("Content-Type", "application/json") | 	req.Header.Add("Content-Type", "application/json") | ||||||
| 	req.Header.Add("Accept", "application/json") | 	req.Header.Add("Accept", "application/json") | ||||||
| @@ -233,14 +282,20 @@ func (b *Bot) CallLLM(prompt string) error { | |||||||
| 	res, err := client.Do(req) | 	res, err := client.Do(req) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		b.log.Error("failed to make request", "error", err, "url", b.cfg.LLMConfig.URL) | 		b.log.Error("failed to make request", "error", err, "url", b.cfg.LLMConfig.URL) | ||||||
| 		return err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 	defer res.Body.Close() | 	defer res.Body.Close() | ||||||
| 	body, err := io.ReadAll(res.Body) | 	body, err := io.ReadAll(res.Body) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		b.log.Error("failed to read resp body", "error", err, "url", b.cfg.LLMConfig.URL) | 		b.log.Error("failed to read resp body", "error", err, "url", b.cfg.LLMConfig.URL) | ||||||
| 		return err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 	b.log.Debug("llm resp", "body", string(body)) | 	b.log.Debug("llm resp", "body", string(body)) | ||||||
| 	return nil | 	// TODO: case where it has other text, not only json | ||||||
|  | 	// TODO: how to know which resp it is? mime or guessser? | ||||||
|  | 	// resp := &MimeResp{} | ||||||
|  | 	// if err := json.Unmarshal(body, &resp); err != nil { | ||||||
|  | 	// 	return nil, err | ||||||
|  | 	// } | ||||||
|  | 	return body, nil | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								todos.md
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								todos.md
									
									
									
									
									
								
							| @@ -8,6 +8,7 @@ | |||||||
| - add html icons of whos turn it is (like an image of big ? when mime is thinking); | - add html icons of whos turn it is (like an image of big ? when mime is thinking); | ||||||
| - there two places for bot to check if its its move: start-game; end-turn; | - there two places for bot to check if its its move: start-game; end-turn; | ||||||
| - remove bot button (if game is not running); | - remove bot button (if game is not running); | ||||||
|  | - show in backlog (and with that in prompt to llm) how many cards are left to open, also additional comment: if guess was right; | ||||||
|  |  | ||||||
| #### sse points | #### sse points | ||||||
| - clue sse update; | - clue sse update; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Grail Finder
					Grail Finder