Feat: save room even if llm failed to properly guess; fix prompt
This commit is contained in:
		| @@ -50,7 +50,7 @@ | |||||||
|     {{template "teamlist" .Room.RedTeam}} |     {{template "teamlist" .Room.RedTeam}} | ||||||
|   </div> |   </div> | ||||||
|   <hr /> |   <hr /> | ||||||
|   <div id="systembox"> |   <div id="systembox" style="overflow-y: auto; max-height: 100px;"> | ||||||
|     Server says: <br> |     Server says: <br> | ||||||
|     <ul> |     <ul> | ||||||
|     {{range .Room.LogJournal}}  |     {{range .Room.LogJournal}}  | ||||||
|   | |||||||
| @@ -248,7 +248,6 @@ func listRooms(allRooms bool) []*models.Room { | |||||||
| 				log.Warn("failed to unmarshal room", "error", err) | 				log.Warn("failed to unmarshal room", "error", err) | ||||||
| 				continue | 				continue | ||||||
| 			} | 			} | ||||||
| 			log.Debug("consider room for list", "room", room, "key", key) |  | ||||||
| 			if room.IsPublic || allRooms { | 			if room.IsPublic || allRooms { | ||||||
| 				publicRooms = append(publicRooms, room) | 				publicRooms = append(publicRooms, room) | ||||||
| 			} | 			} | ||||||
|   | |||||||
| @@ -79,11 +79,11 @@ func HandleFrontLogin(w http.ResponseWriter, r *http.Request) { | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	http.SetCookie(w, cookie) | 	http.SetCookie(w, cookie) | ||||||
| 	tmpl, err := template.ParseGlob("components/*.html") | 	// tmpl, err := template.ParseGlob("components/*.html") | ||||||
| 	if err != nil { | 	// if err != nil { | ||||||
| 		abortWithError(w, err.Error()) | 	// 	abortWithError(w, err.Error()) | ||||||
| 		return | 	// 	return | ||||||
| 	} | 	// } | ||||||
| 	// check if that user was already in db | 	// check if that user was already in db | ||||||
| 	userstate, err := loadState(cleanName) | 	userstate, err := loadState(cleanName) | ||||||
| 	if err != nil || userstate == nil { | 	if err != nil || userstate == nil { | ||||||
| @@ -120,9 +120,10 @@ func HandleFrontLogin(w http.ResponseWriter, r *http.Request) { | |||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	if err := tmpl.ExecuteTemplate(w, "base", fi); err != nil { | 	// if err := tmpl.ExecuteTemplate(w, "base", fi); err != nil { | ||||||
| 		log.Error("failed to execute base template", "error", err) | 	// 	log.Error("failed to execute base template", "error", err) | ||||||
| 	} | 	// } | ||||||
|  | 	http.Redirect(w, r, "/", 302) | ||||||
| } | } | ||||||
|  |  | ||||||
| func makeCookie(username string, remote string) (*http.Cookie, error) { | func makeCookie(username string, remote string) (*http.Cookie, error) { | ||||||
|   | |||||||
| @@ -78,7 +78,7 @@ func HandleShowColor(w http.ResponseWriter, r *http.Request) { | |||||||
| 		Actor:      fi.State.Username, | 		Actor:      fi.State.Username, | ||||||
| 		ActorColor: string(fi.State.Team), | 		ActorColor: string(fi.State.Team), | ||||||
| 		WordColor:  string(color), | 		WordColor:  string(color), | ||||||
| 		Action:     "guessed", | 		Action:     models.ActionTypeGuess, | ||||||
| 		Word:       word, | 		Word:       word, | ||||||
| 	} | 	} | ||||||
| 	fi.Room.ActionHistory = append(fi.Room.ActionHistory, action) | 	fi.Room.ActionHistory = append(fi.Room.ActionHistory, action) | ||||||
| @@ -103,8 +103,8 @@ func HandleShowColor(w http.ResponseWriter, r *http.Request) { | |||||||
| 		action := models.Action{ | 		action := models.Action{ | ||||||
| 			Actor:      fi.State.Username, | 			Actor:      fi.State.Username, | ||||||
| 			ActorColor: string(fi.State.Team), | 			ActorColor: string(fi.State.Team), | ||||||
| 			WordColor:  "black", | 			WordColor:  models.WordColorBlack, | ||||||
| 			Action:     "game over", | 			Action:     models.ActionTypeGameOver, | ||||||
| 		} | 		} | ||||||
| 		fi.Room.OpenedThisTurn = 0 | 		fi.Room.OpenedThisTurn = 0 | ||||||
| 		fi.Room.ThisTurnLimit = 0 | 		fi.Room.ThisTurnLimit = 0 | ||||||
| @@ -124,8 +124,8 @@ func HandleShowColor(w http.ResponseWriter, r *http.Request) { | |||||||
| 			action := models.Action{ | 			action := models.Action{ | ||||||
| 				Actor:      fi.State.Username, | 				Actor:      fi.State.Username, | ||||||
| 				ActorColor: string(fi.State.Team), | 				ActorColor: string(fi.State.Team), | ||||||
| 				WordColor:  "blue", | 				WordColor:  models.WordColorBlue, | ||||||
| 				Action:     "game over", | 				Action:     models.ActionTypeGameOver, | ||||||
| 			} | 			} | ||||||
| 			fi.Room.OpenedThisTurn = 0 | 			fi.Room.OpenedThisTurn = 0 | ||||||
| 			fi.Room.ThisTurnLimit = 0 | 			fi.Room.ThisTurnLimit = 0 | ||||||
| @@ -139,8 +139,8 @@ func HandleShowColor(w http.ResponseWriter, r *http.Request) { | |||||||
| 			action := models.Action{ | 			action := models.Action{ | ||||||
| 				Actor:      fi.State.Username, | 				Actor:      fi.State.Username, | ||||||
| 				ActorColor: string(fi.State.Team), | 				ActorColor: string(fi.State.Team), | ||||||
| 				WordColor:  "red", | 				WordColor:  models.WordColorRed, | ||||||
| 				Action:     "game over", | 				Action:     models.ActionTypeGameOver, | ||||||
| 			} | 			} | ||||||
| 			fi.Room.OpenedThisTurn = 0 | 			fi.Room.OpenedThisTurn = 0 | ||||||
| 			fi.Room.ThisTurnLimit = 0 | 			fi.Room.ThisTurnLimit = 0 | ||||||
|   | |||||||
| @@ -153,9 +153,7 @@ func HandleStartGame(w http.ResponseWriter, r *http.Request) { | |||||||
| 		Actor:      fi.State.Username, | 		Actor:      fi.State.Username, | ||||||
| 		ActorColor: string(fi.State.Team), | 		ActorColor: string(fi.State.Team), | ||||||
| 		WordColor:  string(fi.State.Team), | 		WordColor:  string(fi.State.Team), | ||||||
| 		Action:     "game started", | 		Action:     models.ActionTypeGameStarted, | ||||||
| 		// Word:       clue, |  | ||||||
| 		// Number:     num, |  | ||||||
| 	} | 	} | ||||||
| 	fi.Room.ActionHistory = append(fi.Room.ActionHistory, action) | 	fi.Room.ActionHistory = append(fi.Room.ActionHistory, action) | ||||||
| 	if err := saveFullInfo(fi); err != nil { | 	if err := saveFullInfo(fi); err != nil { | ||||||
|   | |||||||
| @@ -120,42 +120,44 @@ func (b *Bot) StartBot() { | |||||||
| 	for { | 	for { | ||||||
| 		select { | 		select { | ||||||
| 		case <-SignalChanMap[b.BotName]: | 		case <-SignalChanMap[b.BotName]: | ||||||
| 			botJournalName := models.NotifyJournalPrefix + b.RoomID | 			func() { | ||||||
|  | 				// botJournalName := models.NotifyJournalPrefix + b.RoomID | ||||||
| 				b.log.Debug("got signal", "bot-team", b.Team, "bot-role", b.Role) | 				b.log.Debug("got signal", "bot-team", b.Team, "bot-role", b.Role) | ||||||
| 				// get room cards and actions | 				// get room cards and actions | ||||||
| 				room, err := getRoomByID(b.RoomID) | 				room, err := getRoomByID(b.RoomID) | ||||||
| 				if err != nil { | 				if err != nil { | ||||||
| 					b.log.Error("bot loop", "error", err) | 					b.log.Error("bot loop", "error", err) | ||||||
| 				continue | 					return | ||||||
| 			} |  | ||||||
| 			// form prompt |  | ||||||
| 			prompt := b.BuildPrompt(room) |  | ||||||
| 			b.log.Debug("got prompt", "prompt", prompt) |  | ||||||
| 			broker.Notifier.Notifier <- broker.NotificationEvent{ |  | ||||||
| 				EventName: botJournalName, |  | ||||||
| 				Payload:   prompt, |  | ||||||
| 			} |  | ||||||
| 			// call llm |  | ||||||
| 			llmResp, err := b.CallLLM(prompt) |  | ||||||
| 			if err != nil { |  | ||||||
| 				broker.Notifier.Notifier <- broker.NotificationEvent{ |  | ||||||
| 					EventName: botJournalName, |  | ||||||
| 					Payload:   "failed to get bot resp", |  | ||||||
| 				} |  | ||||||
| 				b.log.Error("bot loop", "error", err) |  | ||||||
| 				continue |  | ||||||
| 			} |  | ||||||
| 			tempMap, err := b.LLMParser.ParseBytes(llmResp) |  | ||||||
| 			if err != nil { |  | ||||||
| 				broker.Notifier.Notifier <- broker.NotificationEvent{ |  | ||||||
| 					EventName: botJournalName, |  | ||||||
| 					Payload:   "failed to parse bot resp", |  | ||||||
| 				} |  | ||||||
| 				b.log.Error("bot loop", "error", err, "resp", string(llmResp)) |  | ||||||
| 				continue |  | ||||||
| 				} | 				} | ||||||
| 				eventName := models.NotifyBacklogPrefix + room.ID | 				eventName := models.NotifyBacklogPrefix + room.ID | ||||||
| 				eventPayload := "" | 				eventPayload := "" | ||||||
|  | 				defer func() { // save room | ||||||
|  | 					if err := saveRoom(room); err != nil { | ||||||
|  | 						b.log.Error("failed to save room", "error", err) | ||||||
|  | 						return | ||||||
|  | 					} | ||||||
|  | 					broker.Notifier.Notifier <- broker.NotificationEvent{ | ||||||
|  | 						EventName: eventName, | ||||||
|  | 						Payload:   eventPayload, | ||||||
|  | 					} | ||||||
|  | 				}() | ||||||
|  | 				// form prompt | ||||||
|  | 				prompt := b.BuildPrompt(room) | ||||||
|  | 				b.log.Debug("got prompt", "prompt", prompt) | ||||||
|  | 				room.LogJournal = append(room.LogJournal, b.BotName+" got prompt: "+prompt) | ||||||
|  | 				// call llm | ||||||
|  | 				llmResp, err := b.CallLLM(prompt) | ||||||
|  | 				if err != nil { | ||||||
|  | 					room.LogJournal = append(room.LogJournal, b.BotName+" send call got error: "+err.Error()) | ||||||
|  | 					b.log.Error("bot loop", "error", err) | ||||||
|  | 					return | ||||||
|  | 				} | ||||||
|  | 				tempMap, err := b.LLMParser.ParseBytes(llmResp) | ||||||
|  | 				if err != nil { | ||||||
|  | 					room.LogJournal = append(room.LogJournal, b.BotName+" parse resp got error: "+err.Error()) | ||||||
|  | 					b.log.Error("bot loop", "error", err, "resp", string(llmResp)) | ||||||
|  | 					return | ||||||
|  | 				} | ||||||
| 				switch b.Role { | 				switch b.Role { | ||||||
| 				case models.UserRoleMime: | 				case models.UserRoleMime: | ||||||
| 					mimeResp := MimeResp{} | 					mimeResp := MimeResp{} | ||||||
| @@ -189,7 +191,9 @@ func (b *Bot) StartBot() { | |||||||
| 						b.log.Warn("failed to parse guess", "mimeResp", tempMap, "bot_name", b.BotName) | 						b.log.Warn("failed to parse guess", "mimeResp", tempMap, "bot_name", b.BotName) | ||||||
| 					} | 					} | ||||||
| 					if err := b.checkGuess(guess, room); err != nil { | 					if err := b.checkGuess(guess, room); err != nil { | ||||||
| 					b.log.Warn("failed to check guess", "mimeResp", tempMap, "bot_name", b.BotName, "guess", guess) | 						b.log.Warn("failed to check guess", "mimeResp", tempMap, "bot_name", b.BotName, "guess", guess, "error", err) | ||||||
|  | 						msg := fmt.Sprintf("failed to check guess", "mimeResp", tempMap, "bot_name", b.BotName, "guess", guess, "error", err) | ||||||
|  | 						room.LogJournal = append(room.LogJournal, msg) | ||||||
| 					} | 					} | ||||||
| 					b.log.Info("mime resp log", "guesserResp", tempMap) | 					b.log.Info("mime resp log", "guesserResp", tempMap) | ||||||
| 					couldBe, err := convertToSliceOfStrings(tempMap["could_be"]) | 					couldBe, err := convertToSliceOfStrings(tempMap["could_be"]) | ||||||
| @@ -203,22 +207,13 @@ func (b *Bot) StartBot() { | |||||||
| 				// or end turn on limit | 				// or end turn on limit | ||||||
| 				default: | 				default: | ||||||
| 					b.log.Error("unexpected role", "role", b.Role, "resp-map", tempMap) | 					b.log.Error("unexpected role", "role", b.Role, "resp-map", tempMap) | ||||||
| 				continue | 					return | ||||||
| 			} |  | ||||||
| 			// save room |  | ||||||
| 			if err := saveRoom(room); err != nil { |  | ||||||
| 				b.log.Error("failed to save room", "error", err) |  | ||||||
| 				continue |  | ||||||
| 				} | 				} | ||||||
| 				if botName := room.WhichBotToMove(); botName != "" { | 				if botName := room.WhichBotToMove(); botName != "" { | ||||||
| 					b.log.Debug("notifying bot", "name", botName) | 					b.log.Debug("notifying bot", "name", botName) | ||||||
| 					SignalChanMap[botName] <- true | 					SignalChanMap[botName] <- true | ||||||
| 				} | 				} | ||||||
| 			broker.Notifier.Notifier <- broker.NotificationEvent{ | 			}() | ||||||
| 				EventName: eventName, |  | ||||||
| 				Payload:   eventPayload, |  | ||||||
| 			} |  | ||||||
| 			continue |  | ||||||
| 		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 | ||||||
| @@ -335,13 +330,19 @@ func saveRoom(room *models.Room) error { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (b *Bot) BuildSimpleGuesserPrompt(room *models.Room) string { | func (b *Bot) BuildSimpleGuesserPrompt(room *models.Room) string { | ||||||
| 	clue := room.ActionHistory[len(room.ActionHistory)-1].Word | 	// find not last action, but the clue | ||||||
|  | 	// clue := room.ActionHistory[len(room.ActionHistory)-1].Word | ||||||
|  | 	clueAction, err := room.FetchLastClue() | ||||||
|  | 	if err != nil { | ||||||
|  | 		b.log.Error("failed to fetch last clue", "error", err, "room", room, "bot_name", b.BotName) | ||||||
|  | 		return "" | ||||||
|  | 	} | ||||||
| 	// number := room.ActionHistory[len(room.ActionHistory)-1].Number | 	// number := room.ActionHistory[len(room.ActionHistory)-1].Number | ||||||
| 	words := make([]string, len(room.Cards)) | 	words := make([]string, len(room.Cards)) | ||||||
| 	for i, card := range room.Cards { | 	for i, card := range room.Cards { | ||||||
| 		words[i] = card.Word | 		words[i] = card.Word | ||||||
| 	} | 	} | ||||||
| 	return fmt.Sprintf(GuesserSimplePrompt, clue, words) | 	return fmt.Sprintf(GuesserSimplePrompt, clueAction.Word, words) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *Bot) BuildPrompt(room *models.Room) string { | func (b *Bot) BuildPrompt(room *models.Room) string { | ||||||
|   | |||||||
| @@ -19,6 +19,15 @@ const ( | |||||||
| 	WordColorUknown = "stone" // beige | 	WordColorUknown = "stone" // beige | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | type ActionType string | ||||||
|  |  | ||||||
|  | const ( | ||||||
|  | 	ActionTypeClue        = "gave_clue" | ||||||
|  | 	ActionTypeGuess       = "guessed" | ||||||
|  | 	ActionTypeGameOver    = "game_over" | ||||||
|  | 	ActionTypeGameStarted = "game_started" | ||||||
|  | ) | ||||||
|  |  | ||||||
| func StrToWordColor(s string) WordColor { | func StrToWordColor(s string) WordColor { | ||||||
| 	switch s { | 	switch s { | ||||||
| 	case "amber", "white": | 	case "amber", "white": | ||||||
| @@ -88,6 +97,15 @@ type Room struct { | |||||||
| 	LogJournal []string | 	LogJournal []string | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (r *Room) FetchLastClue() (*Action, error) { | ||||||
|  | 	for i := len(r.ActionHistory) - 1; i >= 0; i-- { | ||||||
|  | 		if r.ActionHistory[i].Action == string(ActionTypeClue) { | ||||||
|  | 			return &r.ActionHistory[i], nil | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return nil, errors.New("no clue in history") | ||||||
|  | } | ||||||
|  |  | ||||||
| func (r *Room) GetPlayerByName(name string) (role UserRole, team UserTeam, found bool) { | func (r *Room) GetPlayerByName(name string) (role UserRole, team UserTeam, found bool) { | ||||||
| 	if r.RedTeam.Mime == name { | 	if r.RedTeam.Mime == name { | ||||||
| 		return "mime", "red", true | 		return "mime", "red", true | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Grail Finder
					Grail Finder