Feat: remove bot
This commit is contained in:
		
							
								
								
									
										204
									
								
								llmapi/main.go
									
									
									
									
									
								
							
							
						
						
									
										204
									
								
								llmapi/main.go
									
									
									
									
									
								
							| @@ -77,7 +77,7 @@ func (b *Bot) checkGuess(word string, room *models.Room) error { | ||||
| 		Actor:      b.BotName, | ||||
| 		ActorColor: b.Team, | ||||
| 		WordColor:  string(color), | ||||
| 		Action:     "guessed", | ||||
| 		Action:     models.ActionTypeGuess, | ||||
| 		Word:       word, | ||||
| 	} | ||||
| 	room.ActionHistory = append(room.ActionHistory, action) | ||||
| @@ -115,105 +115,107 @@ func (b *Bot) checkGuess(word string, room *models.Room) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (b *Bot) BotMove() { | ||||
| 	// botJournalName := models.NotifyJournalPrefix + b.RoomID | ||||
| 	b.log.Debug("got signal", "bot-team", b.Team, "bot-role", b.Role) | ||||
| 	// get room cards and actions | ||||
| 	room, err := getRoomByID(b.RoomID) | ||||
| 	if err != nil { | ||||
| 		b.log.Error("bot loop", "error", err) | ||||
| 		return | ||||
| 	} | ||||
| 	eventName := models.NotifyBacklogPrefix + room.ID | ||||
| 	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 { | ||||
| 	case models.UserRoleMime: | ||||
| 		mimeResp := MimeResp{} | ||||
| 		b.log.Info("mime resp log", "mimeResp", tempMap) | ||||
| 		mimeResp.Clue = tempMap["clue"].(string) | ||||
| 		mimeResp.Number = tempMap["number"].(string) | ||||
| 		action := models.Action{ | ||||
| 			Actor:      b.BotName, | ||||
| 			ActorColor: b.Team, | ||||
| 			WordColor:  b.Team, | ||||
| 			Action:     models.ActionTypeClue, | ||||
| 			Word:       mimeResp.Clue, | ||||
| 			Number:     mimeResp.Number, | ||||
| 		} | ||||
| 		room.ActionHistory = append(room.ActionHistory, action) | ||||
| 		room.MimeDone = true | ||||
| 		eventPayload = mimeResp.Clue + mimeResp.Number | ||||
| 		guessLimitU64, err := strconv.ParseUint(mimeResp.Number, 10, 8) | ||||
| 		if err != nil { | ||||
| 			b.log.Warn("failed to parse bot given limit", "mimeResp", mimeResp, "bot_name", b.BotName) | ||||
| 		} | ||||
| 		room.ThisTurnLimit = uint8(guessLimitU64) | ||||
| 	case models.UserRoleGuesser: | ||||
| 		// // deprecated | ||||
| 		// if err := b.checkGuesses(tempMap, room); err != nil { | ||||
| 		// 	b.log.Warn("failed to check guess", "mimeResp", tempMap, "bot_name", b.BotName) | ||||
| 		// 	continue | ||||
| 		// } | ||||
| 		guess, ok := tempMap["guess"].(string) | ||||
| 		if !ok || guess == "" { | ||||
| 			b.log.Warn("failed to parse guess", "mimeResp", tempMap, "bot_name", b.BotName) | ||||
| 		} | ||||
| 		if err := b.checkGuess(guess, room); err != nil { | ||||
| 			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) | ||||
| 		couldBe, err := convertToSliceOfStrings(tempMap["could_be"]) | ||||
| 		if err != nil { | ||||
| 			b.log.Warn("failed to parse could_be", "bot_resp", tempMap, "bot_name", b.BotName) | ||||
| 		} | ||||
| 		room.LogJournal = append(room.LogJournal, fmt.Sprintf("%s also considered this: %v", b.BotName, couldBe)) | ||||
| 		eventName = models.NotifyRoomUpdatePrefix + room.ID | ||||
| 		eventPayload = "" | ||||
| 	// TODO: needs to decide if it wants to open the next cardword or end turn | ||||
| 	// or end turn on limit | ||||
| 	default: | ||||
| 		b.log.Error("unexpected role", "role", b.Role, "resp-map", tempMap) | ||||
| 		return | ||||
| 	} | ||||
| 	if botName := room.WhichBotToMove(); botName != "" { | ||||
| 		b.log.Debug("notifying bot", "name", botName) | ||||
| 		SignalChanMap[botName] <- true | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // StartBot | ||||
| func (b *Bot) StartBot() { | ||||
| 	for { | ||||
| 		select { | ||||
| 		case <-SignalChanMap[b.BotName]: | ||||
| 			func() { | ||||
| 				// botJournalName := models.NotifyJournalPrefix + b.RoomID | ||||
| 				b.log.Debug("got signal", "bot-team", b.Team, "bot-role", b.Role) | ||||
| 				// get room cards and actions | ||||
| 				room, err := getRoomByID(b.RoomID) | ||||
| 				if err != nil { | ||||
| 					b.log.Error("bot loop", "error", err) | ||||
| 					return | ||||
| 				} | ||||
| 				eventName := models.NotifyBacklogPrefix + room.ID | ||||
| 				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 { | ||||
| 				case models.UserRoleMime: | ||||
| 					mimeResp := MimeResp{} | ||||
| 					b.log.Info("mime resp log", "mimeResp", tempMap) | ||||
| 					mimeResp.Clue = tempMap["clue"].(string) | ||||
| 					mimeResp.Number = tempMap["number"].(string) | ||||
| 					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 | ||||
| 					eventPayload = mimeResp.Clue + mimeResp.Number | ||||
| 					guessLimitU64, err := strconv.ParseUint(mimeResp.Number, 10, 8) | ||||
| 					if err != nil { | ||||
| 						b.log.Warn("failed to parse bot given limit", "mimeResp", mimeResp, "bot_name", b.BotName) | ||||
| 					} | ||||
| 					room.ThisTurnLimit = uint8(guessLimitU64) | ||||
| 				case models.UserRoleGuesser: | ||||
| 					// // deprecated | ||||
| 					// if err := b.checkGuesses(tempMap, room); err != nil { | ||||
| 					// 	b.log.Warn("failed to check guess", "mimeResp", tempMap, "bot_name", b.BotName) | ||||
| 					// 	continue | ||||
| 					// } | ||||
| 					guess, ok := tempMap["guess"].(string) | ||||
| 					if !ok || guess == "" { | ||||
| 						b.log.Warn("failed to parse guess", "mimeResp", tempMap, "bot_name", b.BotName) | ||||
| 					} | ||||
| 					if err := b.checkGuess(guess, room); err != nil { | ||||
| 						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) | ||||
| 					couldBe, err := convertToSliceOfStrings(tempMap["could_be"]) | ||||
| 					if err != nil { | ||||
| 						b.log.Warn("failed to parse could_be", "bot_resp", tempMap, "bot_name", b.BotName) | ||||
| 					} | ||||
| 					room.LogJournal = append(room.LogJournal, fmt.Sprintf("%s also considered this: %v", b.BotName, couldBe)) | ||||
| 					eventName = models.NotifyRoomUpdatePrefix + room.ID | ||||
| 					eventPayload = "" | ||||
| 				// TODO: needs to decide if it wants to open the next cardword or end turn | ||||
| 				// or end turn on limit | ||||
| 				default: | ||||
| 					b.log.Error("unexpected role", "role", b.Role, "resp-map", tempMap) | ||||
| 					return | ||||
| 				} | ||||
| 				if botName := room.WhichBotToMove(); botName != "" { | ||||
| 					b.log.Debug("notifying bot", "name", botName) | ||||
| 					SignalChanMap[botName] <- true | ||||
| 				} | ||||
| 			}() | ||||
| 			b.BotMove() | ||||
| 		case <-DoneChanMap[b.BotName]: | ||||
| 			b.log.Debug("got done signal", "bot-name", b.BotName) | ||||
| 			return | ||||
| @@ -221,6 +223,18 @@ func (b *Bot) StartBot() { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func RemoveBot(botName string, room *models.Room) error { | ||||
| 	// channels | ||||
| 	DoneChanMap[botName] <- true | ||||
| 	close(DoneChanMap[botName]) | ||||
| 	close(SignalChanMap[botName]) | ||||
| 	// maps | ||||
| 	delete(room.BotMap, botName) | ||||
| 	delete(DoneChanMap, botName) | ||||
| 	delete(SignalChanMap, botName) | ||||
| 	return saveRoom(room) | ||||
| } | ||||
|  | ||||
| // EndBot | ||||
|  | ||||
| func NewBot(role, team, name, roomID string, cfg *config.Config, recovery bool) (*Bot, error) { | ||||
|   | ||||
| @@ -160,8 +160,10 @@ func (p *openRouterParser) ParseBytes(body []byte) (map[string]any, error) { | ||||
| } | ||||
|  | ||||
| func (p *openRouterParser) MakePayload(prompt string) io.Reader { | ||||
| 	// "model": "deepseek/deepseek-chat-v3-0324:free", | ||||
| 	// TODO: set list of models an option to pick on the frontend | ||||
| 	strPayload := fmt.Sprintf(`{ | ||||
| 	"model": "deepseek/deepseek-chat-v3-0324:free", | ||||
| 	"model": "google/gemini-2.0-flash-exp:free", | ||||
| 	"messages": [ | ||||
| 		{ | ||||
| 		"role": "user", | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Grail Finder
					Grail Finder