Ctrl K
ComunidadGuías…

internal/memory/run_answers.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package memory

import (
	"context"
	"encoding/json"
	"sort"
	"strings"

	"github.com/yeomyeonggeori/bluememo"
	"github.com/yeomyeonggeori/blueprotocol/agentcontract"
)

// runAnswers is the layer of what a task run's tools answered. The record a
// run read and the changes it made live in the systems that answered, so a
// memory restating one would be a second copy that goes stale the day the
// record moves. Ranking here only orders what the judge is shown; the judge
// decides whether a statement says what an answer said.
type runAnswers []bluememo.Memory

func answersOf(events []agentcontract.TaskEvent) runAnswers {
	answers := runAnswers{}
	for _, event := range events {
		if _, isResult := agentcontract.ToolTaskEventToolName(event.Name, agentcontract.ToolTaskEventResultSuffix); !isResult {
			continue
		}
		var observation struct {
			ObservationID string          `json:"observationID"`
			Summary       string          `json:"summary"`
			Failure       json.RawMessage `json:"failure"`
		}
		if json.Unmarshal([]byte(event.Body), &observation) != nil || hasFailure(observation.Failure) {
			continue
		}
		if summary := strings.TrimSpace(observation.Summary); summary != "" {
			answers = append(answers, bluememo.Memory{MemoryID: "answer-" + observation.ObservationID, Content: summary})
		}
	}
	return answers
}

func hasFailure(failure json.RawMessage) bool {
	trimmed := strings.TrimSpace(string(failure))
	return trimmed != "" && trimmed != "null"
}

func (answers runAnswers) Search(_ context.Context, query string, limit int) ([]bluememo.RecalledMemory, error) {
	queryPairs := runePairs(query)
	ranked := []bluememo.RecalledMemory{}
	for _, answer := range answers {
		if shared := sharedCount(queryPairs, runePairs(answer.Content)); shared > 0 {
			ranked = append(ranked, bluememo.RecalledMemory{Memory: answer, Score: float64(shared) / float64(len(queryPairs))})
		}
	}
	sort.SliceStable(ranked, func(first, second int) bool { return ranked[first].Score > ranked[second].Score })
	return ranked[:min(len(ranked), limit)], nil
}

func runePairs(text string) map[string]bool {
	runes := []rune(strings.ToLower(strings.Join(strings.Fields(text), " ")))
	pairs := map[string]bool{}
	for index := 0; index+1 < len(runes); index++ {
		pairs[string(runes[index:index+2])] = true
	}
	return pairs
}

func sharedCount(first map[string]bool, second map[string]bool) int {
	count := 0
	for pair := range first {
		if second[pair] {
			count++
		}
	}
	return count
}