fix: address Copilot review feedback

- Validate --model is required for LLM eval mode
- Use rune-based truncation to preserve valid UTF-8
- Precompute totalQA count outside inner loop
- Log SearchMessages errors instead of silently skipping
This commit is contained in:
BeaconCat 2026-04-12 16:06:15 +08:00
parent aa894e6c7c
commit 29b94bf75f
2 changed files with 14 additions and 5 deletions

View file

@ -27,9 +27,10 @@ Output ONLY the number, nothing else.`
// generateAnswer asks the LLM to answer a question given retrieved context. // generateAnswer asks the LLM to answer a question given retrieved context.
func generateAnswer(ctx context.Context, client *LLMClient, contextText, question string) (string, error) { func generateAnswer(ctx context.Context, client *LLMClient, contextText, question string) (string, error) {
// Truncate context to avoid exceeding model limits // Truncate context to avoid exceeding model limits while preserving valid UTF-8.
if len(contextText) > 6000 { contextRunes := []rune(contextText)
contextText = contextText[:6000] + "\n... [truncated]" if len(contextRunes) > 6000 {
contextText = string(contextRunes[:6000]) + "\n... [truncated]"
} }
userPrompt := fmt.Sprintf("## Conversation Context\n\n%s\n\n## Question\n\n%s", contextText, question) userPrompt := fmt.Sprintf("## Conversation Context\n\n%s\n\n## Question\n\n%s", contextText, question)
@ -74,6 +75,7 @@ func EvalLegacyLLM(
budgetTokens int, budgetTokens int,
client *LLMClient, client *LLMClient,
) []EvalResult { ) []EvalResult {
totalQA := countTotalQA(samples)
results := make([]EvalResult, 0, len(samples)) results := make([]EvalResult, 0, len(samples))
total := 0 total := 0
for si := range samples { for si := range samples {
@ -119,7 +121,7 @@ func EvalLegacyLLM(
}) })
log.Printf("[legacy-llm] sample=%s q=%d/%d score=%.2f answer=%q", log.Printf("[legacy-llm] sample=%s q=%d/%d score=%.2f answer=%q",
sample.SampleID, total, countTotalQA(samples), score, truncateStr(llmAnswer, 80)) sample.SampleID, total, totalQA, score, truncateStr(llmAnswer, 80))
} }
results = append(results, EvalResult{ results = append(results, EvalResult{
@ -143,6 +145,7 @@ func EvalSeahorseLLM(
store := ir.Engine.GetRetrieval().Store() store := ir.Engine.GetRetrieval().Store()
retrieval := ir.Engine.GetRetrieval() retrieval := ir.Engine.GetRetrieval()
totalQA := countTotalQA(samples)
results := make([]EvalResult, 0, len(samples)) results := make([]EvalResult, 0, len(samples))
total := 0 total := 0
for si := range samples { for si := range samples {
@ -168,6 +171,7 @@ func EvalSeahorseLLM(
Limit: 20, Limit: 20,
}) })
if err != nil { if err != nil {
log.Printf("WARN: search failed for keyword %q: %v", kw, err)
continue continue
} }
for _, sr := range searchResults { for _, sr := range searchResults {
@ -232,7 +236,7 @@ func EvalSeahorseLLM(
}) })
log.Printf("[seahorse-llm] sample=%s q=%d/%d score=%.2f answer=%q", log.Printf("[seahorse-llm] sample=%s q=%d/%d score=%.2f answer=%q",
sample.SampleID, total, countTotalQA(samples), score, truncateStr(llmAnswer, 80)) sample.SampleID, total, totalQA, score, truncateStr(llmAnswer, 80))
} }
results = append(results, EvalResult{ results = append(results, EvalResult{

View file

@ -284,6 +284,11 @@ func buildLLMOptions() (LLMClientOptions, error) {
base = "http://127.0.0.1:8080" base = "http://127.0.0.1:8080"
} }
model := envOrFlag(flagModel, "MEMBENCH_MODEL") model := envOrFlag(flagModel, "MEMBENCH_MODEL")
if model == "" {
return LLMClientOptions{}, fmt.Errorf(
"--model or MEMBENCH_MODEL is required for LLM eval mode",
)
}
apiKey := envOrFlag(flagAPIKey, "MEMBENCH_API_KEY") apiKey := envOrFlag(flagAPIKey, "MEMBENCH_API_KEY")
return LLMClientOptions{ return LLMClientOptions{