From 4c2adc636bd09ddc73ef01cd2a8e9cbaf8411a17 Mon Sep 17 00:00:00 2001 From: Steve White Date: Sat, 25 Jan 2025 20:56:23 -0600 Subject: [PATCH] More armoring of decision parsing. --- paperprocessor.go | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/paperprocessor.go b/paperprocessor.go index f942354..799c155 100644 --- a/paperprocessor.go +++ b/paperprocessor.go @@ -180,18 +180,29 @@ Abstract: %s`, criteria, paper.Title, paper.Abstract) } content := llmResp.Choices[0].Message.Content - lines := bytes.Split([]byte(content), []byte("\n")) - if len(lines) < 2 { - return nil, fmt.Errorf("invalid response format") + // Find first line with ACCEPT/REJECT + var decisionLine string + lines := bytes.Split([]byte(content), []byte("\n")) + for _, line := range lines { + if strings.Contains(strings.ToUpper(string(line)), "ACCEPT") || + strings.Contains(strings.ToUpper(string(line)), "REJECT") { + decisionLine = string(line) + break + } + } + + if decisionLine == "" { + return nil, fmt.Errorf("no decision found in response. Full response:\n%s", content) } // Clean and normalize decision - rawDecision := string(bytes.TrimSpace(lines[0])) + rawDecision := strings.TrimSpace(decisionLine) - // Remove any non-alphabetic characters from start/end - cleanDecision := strings.TrimFunc(rawDecision, func(r rune) bool { - return !unicode.IsLetter(r) + // Remove "DECISION:" prefix if present and trim non-alphabetic characters + cleanDecision := strings.TrimPrefix(rawDecision, "DECISION:") + cleanDecision = strings.TrimFunc(cleanDecision, func(r rune) bool { + return !unicode.IsLetter(r) && !unicode.IsNumber(r) }) // Normalize case and check for valid decision @@ -203,10 +214,12 @@ Abstract: %s`, criteria, paper.Title, paper.Abstract) case strings.HasPrefix(upperDecision, "REJECT"): decision = "REJECT" default: - return nil, fmt.Errorf("invalid decision value: %q (cleaned: %q)", rawDecision, cleanDecision) + return nil, fmt.Errorf("invalid decision value: %q (cleaned: %q). Full response:\n%s", + rawDecision, cleanDecision, content) } - explanation := string(bytes.TrimSpace(bytes.Join(lines[1:], []byte("\n")))) + // Get explanation as everything after the decision line + explanation := strings.TrimSpace(strings.Replace(content, decisionLine, "", 1)) return &decisionResult{ Decision: decision,