Enha: llm errors to journal

This commit is contained in:
Grail Finder
2025-07-11 14:12:05 +03:00
parent 3cb43d5129
commit 7beccb84a2
2 changed files with 45 additions and 13 deletions

View File

@ -222,21 +222,27 @@ func (b *Bot) BotMove() {
// call llm // call llm
llmResp, err := b.CallLLM(prompt) llmResp, err := b.CallLLM(prompt)
if err != nil { if err != nil {
room.LogJournal = append(room.LogJournal, models.Journal{ lj := models.Journal{
Entry: "send call got error: " + err.Error(), Entry: fmt.Sprintf("bot '%s' exceeded attempts to call llm;", b.BotName),
Username: b.BotName, Username: b.BotName,
RoomID: room.ID, RoomID: b.RoomID,
}) }
if err := repo.JournalCreate(context.Background(), &lj); err != nil {
b.log.Warn("failed to write to journal", "entry", lj)
}
b.log.Error("bot loop", "error", err) b.log.Error("bot loop", "error", err)
return return
} }
tempMap, err := b.LLMParser.ParseBytes(llmResp) tempMap, err := b.LLMParser.ParseBytes(llmResp)
if err != nil { if err != nil {
room.LogJournal = append(room.LogJournal, models.Journal{ lj := models.Journal{
Entry: "parse resp got error: " + err.Error(), Entry: fmt.Sprintf("bot '%s' parsing resp failed;", b.BotName),
Username: b.BotName, Username: b.BotName,
RoomID: room.ID, RoomID: b.RoomID,
}) }
if err := repo.JournalCreate(context.Background(), &lj); err != nil {
b.log.Warn("failed to write to journal", "entry", lj)
}
b.log.Error("bot loop", "error", err, "resp", string(llmResp)) b.log.Error("bot loop", "error", err, "resp", string(llmResp))
return return
} }
@ -245,6 +251,22 @@ func (b *Bot) BotMove() {
mimeResp := MimeResp{} mimeResp := MimeResp{}
b.log.Info("mime resp log", "mimeResp", tempMap) b.log.Info("mime resp log", "mimeResp", tempMap)
mimeResp.Clue = strings.ToLower(tempMap["clue"].(string)) mimeResp.Clue = strings.ToLower(tempMap["clue"].(string))
for _, card := range room.Cards {
if strings.ToLower(card.Word) == mimeResp.Clue {
b.log.Warn("bot-mime clue is one of the words on the board; retrying", "clue", mimeResp.Clue, "bot", b.BotName)
entry := fmt.Sprintf("bot-mime '%s' gave a clue '%s' which is one of the words on the board. retrying.", b.BotName, mimeResp.Clue)
lj := models.Journal{
Entry: entry,
Username: b.BotName,
RoomID: room.ID,
}
room.LogJournal = append(room.LogJournal, lj)
if err := repo.JournalCreate(context.Background(), &lj); err != nil {
b.log.Warn("failed to write to journal", "entry", lj)
}
return
}
}
var ok bool var ok bool
mimeResp.Number, ok = tempMap["number"].(string) mimeResp.Number, ok = tempMap["number"].(string)
if !ok { if !ok {
@ -596,7 +618,7 @@ func (b *Bot) CallLLM(prompt string) ([]byte, error) {
req, err := http.NewRequest(method, b.cfg.LLMConfig.URL, payloadReader) req, err := http.NewRequest(method, b.cfg.LLMConfig.URL, payloadReader)
if err != nil { if err != nil {
if attempt == maxRetries-1 { if attempt == maxRetries-1 {
return nil, fmt.Errorf("failed to create request: %w", err) return nil, fmt.Errorf("LLM call failed after %d retries on request creation: %w", maxRetries, err)
} }
b.log.Error("failed to make new request; will retry", "error", err, "url", b.cfg.LLMConfig.URL, "attempt", attempt) b.log.Error("failed to make new request; will retry", "error", err, "url", b.cfg.LLMConfig.URL, "attempt", attempt)
time.Sleep(time.Duration(baseDelay) * time.Second * time.Duration(attempt+1)) time.Sleep(time.Duration(baseDelay) * time.Second * time.Duration(attempt+1))
@ -608,7 +630,7 @@ func (b *Bot) CallLLM(prompt string) ([]byte, error) {
resp, err := client.Do(req) resp, err := client.Do(req)
if err != nil { if err != nil {
if attempt == maxRetries-1 { if attempt == maxRetries-1 {
return nil, fmt.Errorf("http request failed: %w", err) return nil, fmt.Errorf("LLM call failed after %d retries on client.Do: %w", maxRetries, err)
} }
b.log.Error("http request failed; will retry", "error", err, "url", b.cfg.LLMConfig.URL, "attempt", attempt) b.log.Error("http request failed; will retry", "error", err, "url", b.cfg.LLMConfig.URL, "attempt", attempt)
delay := time.Duration(baseDelay*(attempt+1)) * time.Second delay := time.Duration(baseDelay*(attempt+1)) * time.Second
@ -619,7 +641,7 @@ func (b *Bot) CallLLM(prompt string) ([]byte, error) {
resp.Body.Close() resp.Body.Close()
if err != nil { if err != nil {
if attempt == maxRetries-1 { if attempt == maxRetries-1 {
return nil, fmt.Errorf("failed to read response body: %w", err) return nil, fmt.Errorf("LLM call failed after %d retries on reading body: %w", maxRetries, err)
} }
b.log.Error("failed to read response body; will retry", "error", err, "url", b.cfg.LLMConfig.URL, "attempt", attempt) b.log.Error("failed to read response body; will retry", "error", err, "url", b.cfg.LLMConfig.URL, "attempt", attempt)
delay := time.Duration(baseDelay*(attempt+1)) * time.Second delay := time.Duration(baseDelay*(attempt+1)) * time.Second
@ -629,7 +651,7 @@ func (b *Bot) CallLLM(prompt string) ([]byte, error) {
// Check status code // Check status code
if resp.StatusCode >= 400 && resp.StatusCode < 600 { if resp.StatusCode >= 400 && resp.StatusCode < 600 {
if attempt == maxRetries-1 { if attempt == maxRetries-1 {
return nil, fmt.Errorf("after %d retries, still got status %d", maxRetries, resp.StatusCode) return nil, fmt.Errorf("LLM call failed after %d retries, got status %d", maxRetries, resp.StatusCode)
} }
b.log.Warn("retriable status code; will retry", "code", resp.StatusCode, "attempt", attempt) b.log.Warn("retriable status code; will retry", "code", resp.StatusCode, "attempt", attempt)
delay := time.Duration((baseDelay * (1 << attempt))) * time.Second delay := time.Duration((baseDelay * (1 << attempt))) * time.Second
@ -644,7 +666,16 @@ func (b *Bot) CallLLM(prompt string) ([]byte, error) {
b.log.Debug("llm resp", "body", string(body), "url", b.cfg.LLMConfig.URL, "attempt", attempt) b.log.Debug("llm resp", "body", string(body), "url", b.cfg.LLMConfig.URL, "attempt", attempt)
return body, nil return body, nil
} }
entry := fmt.Sprintf("bot '%s' exceeded attempts to call llm;", b.BotName)
lj := models.Journal{
Entry: entry,
Username: b.BotName,
RoomID: b.RoomID,
}
if err := repo.JournalCreate(context.Background(), &lj); err != nil {
b.log.Warn("failed to write to journal", "entry", lj)
}
// notify room
// This line should not be reached because each error path returns in the loop. // This line should not be reached because each error path returns in the loop.
return nil, errors.New("unknown error in retry loop") return nil, errors.New("unknown error in retry loop")
} }

View File

@ -34,6 +34,7 @@
- at game creation list languages and support them at backend; + - at game creation list languages and support them at backend; +
- sql ping goroutine with reconnect on fail; + - sql ping goroutine with reconnect on fail; +
- player stats: played games, lost, won, rating elo, opened opposite words, opened white words, opened black words. - player stats: played games, lost, won, rating elo, opened opposite words, opened white words, opened black words.
- at the end of the game, all colors should be revealed;
#### sse points #### sse points
- clue sse update; - clue sse update;