Tab/space alignment consistency from running gofmt on all packages. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
116 lines
3.4 KiB
Go
116 lines
3.4 KiB
Go
// Package prompt assembles evolution prompts for the LLM ensemble.
|
|
package prompt
|
|
|
|
import (
|
|
evolverdb "github.com/aicodebattle/acb/cmd/acb-evolver/internal/db"
|
|
"github.com/aicodebattle/acb/cmd/acb-evolver/internal/meta"
|
|
"github.com/aicodebattle/acb/cmd/acb-evolver/internal/replay"
|
|
)
|
|
|
|
// FromReplayAnalysis converts a replay.Analysis to a prompt.MatchSummary.
|
|
// This allows the prompt builder to consume output from the replay analyzer.
|
|
func FromReplayAnalysis(a *replay.Analysis) MatchSummary {
|
|
if a == nil {
|
|
return MatchSummary{}
|
|
}
|
|
return MatchSummary{
|
|
MatchID: a.MatchID,
|
|
WinnerName: a.WinnerName,
|
|
LoserName: a.LoserName,
|
|
Condition: a.Condition,
|
|
TurnCount: a.TurnCount,
|
|
Scores: append([]int(nil), a.Scores...), // copy to avoid aliasing
|
|
KeyMoments: append([]string(nil), a.KeyMoments...),
|
|
Strategies: append([]string(nil), a.Strategies...),
|
|
Weaknesses: append([]string(nil), a.Weaknesses...),
|
|
}
|
|
}
|
|
|
|
// FromReplayAnalyses converts multiple replay analyses to match summaries.
|
|
func FromReplayAnalyses(analyses []*replay.Analysis) []MatchSummary {
|
|
if len(analyses) == 0 {
|
|
return nil
|
|
}
|
|
summaries := make([]MatchSummary, len(analyses))
|
|
for i, a := range analyses {
|
|
summaries[i] = FromReplayAnalysis(a)
|
|
}
|
|
return summaries
|
|
}
|
|
|
|
// FromMetaDescription converts a meta.Description to a prompt.MetaDescription.
|
|
// This allows the prompt builder to consume output from the meta builder.
|
|
func FromMetaDescription(d *meta.Description) MetaDescription {
|
|
if d == nil {
|
|
return MetaDescription{}
|
|
}
|
|
return MetaDescription{
|
|
TotalBots: d.TotalBots,
|
|
DominantStrategy: d.DominantStrategy,
|
|
NashMixture: d.NashMixture,
|
|
MetaWeaknesses: append([]string(nil), d.MetaWeaknesses...),
|
|
TopBots: FromBotInfos(d.TopBots),
|
|
IslandStats: FromIslandStatsMap(d.IslandStats),
|
|
}
|
|
}
|
|
|
|
// FromBotInfos converts meta.BotInfo slices to prompt.BotSummary slices.
|
|
func FromBotInfos(bots []meta.BotInfo) []BotSummary {
|
|
if len(bots) == 0 {
|
|
return nil
|
|
}
|
|
result := make([]BotSummary, len(bots))
|
|
for i, b := range bots {
|
|
result[i] = BotSummary{
|
|
Name: b.Name,
|
|
Rating: b.Rating,
|
|
Island: b.Island,
|
|
Evolved: b.Evolved,
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
// FromIslandStatsMap converts meta island stats to prompt island stats.
|
|
func FromIslandStatsMap(stats map[string]meta.IslandStats) map[string]IslandStat {
|
|
if stats == nil {
|
|
return nil
|
|
}
|
|
result := make(map[string]IslandStat, len(stats))
|
|
for k, v := range stats {
|
|
result[k] = IslandStat{
|
|
Count: v.Count,
|
|
AvgFitness: v.AvgFitness,
|
|
TopFitness: v.TopFitness,
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
// BuildRequest is a convenience function that assembles a prompt.Request
|
|
// from the standard evolution pipeline components.
|
|
//
|
|
// Parameters:
|
|
// - parents: programs selected as evolutionary parents (from tournament selection)
|
|
// - analyses: replay analyses from recent matches
|
|
// - metaDesc: meta-game description from the meta builder
|
|
// - island: target island for the new candidate
|
|
// - targetLang: programming language for the evolved bot
|
|
// - generation: current evolution generation number
|
|
func BuildRequest(
|
|
parents []*evolverdb.Program,
|
|
analyses []*replay.Analysis,
|
|
metaDesc *meta.Description,
|
|
island string,
|
|
targetLang string,
|
|
generation int,
|
|
) Request {
|
|
return Request{
|
|
Parents: parents,
|
|
Replays: FromReplayAnalyses(analyses),
|
|
Meta: FromMetaDescription(metaDesc),
|
|
Island: island,
|
|
TargetLang: targetLang,
|
|
Generation: generation,
|
|
}
|
|
}
|