mirror of
https://github.com/nolen777/eagle0.git
synced 2026-07-28 20:55:44 +00:00
Stage 1: Stop displaying battalion backstories in client (#6001)
Disable the battalion backstory popup that appears on hover in the Heroes & Battalions panel. This is the first stage of eliminating battalion backstory LLM updates to reduce request volume. The popup panel is now always hidden when hovering over battalions. Hero backstories are unaffected. See docs/eliminate-battalion-backstory-updates.md for the full plan. Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,230 @@
|
||||
# Plan: Eliminate Battalion Backstory LLM Updates
|
||||
|
||||
## Goal
|
||||
|
||||
Dramatically reduce LLM request volume by eliminating battalion backstory updates. Battalions will retain:
|
||||
- An **initial backstory** (generated once when created)
|
||||
- A **history of events** (structured data, not LLM-generated prose)
|
||||
|
||||
The history will be fed into other LLM updates (hero backstories, chronicle) but will no longer be regenerated into prose for each battalion.
|
||||
|
||||
## Current System Overview
|
||||
|
||||
### Data Flow
|
||||
```
|
||||
Battalion Created → Initial Backstory LLM Request → Text stored
|
||||
↓
|
||||
Battalion participates in events → Events accumulated → Update LLM Request → New text version
|
||||
↓
|
||||
BattalionView.backstoryTextId → Client displays on hover
|
||||
```
|
||||
|
||||
### Event Types (8 total)
|
||||
Events are structured data already captured in `EventForBattalionBackstory`:
|
||||
- OrganizedTroops, SuppressedBeasts, ApprehendedOutlaws, FoughtInBattle
|
||||
- SuppressedRiot, Trained, Armed, SurvivedStarvation
|
||||
|
||||
Each event has date, province, hero, and event-specific details.
|
||||
|
||||
### Key Files
|
||||
|
||||
| Component | File |
|
||||
|-----------|------|
|
||||
| Unity Display | `Assets/Eagle/HeroesAndBattalionsPanelController.cs` |
|
||||
| View Proto | `views/battalion_view.proto` |
|
||||
| View Filter | `BattalionViewFilter.scala` |
|
||||
| Update Action | `BattalionBackstoryUpdateAction.scala` |
|
||||
| Update Generator | `BattalionBackstoryUpdateActionGenerator.scala` |
|
||||
| Update Prompt | `BattalionBackstoryUpdatePromptGenerator.scala` |
|
||||
| Event-to-Text | `BattalionBackstoryUpdatePromptGenerator.textForEvent()` |
|
||||
| BattalionDescriptions | `BattalionDescriptions.scala` (used in other LLM prompts) |
|
||||
|
||||
---
|
||||
|
||||
## Stage 1: Stop Displaying Battalion Backstories in Client
|
||||
|
||||
**Goal:** Remove the UI that shows battalion backstory text on hover.
|
||||
|
||||
### Files to Modify
|
||||
|
||||
**`Assets/Eagle/HeroesAndBattalionsPanelController.cs`**
|
||||
- In `BattalionLongHoverRowChanged()` (lines 143-169):
|
||||
- Remove or comment out the backstory text population
|
||||
- Keep the header/name display, remove `battalionPopupPanelBackstory.TextId = ...`
|
||||
|
||||
**Unity Scene/Prefab**
|
||||
- Hide or remove the `battalionPopupPanelBackstory` UI element
|
||||
|
||||
### Verification
|
||||
- [ ] Battalion hover popup no longer shows backstory text
|
||||
- [ ] No errors when hovering over battalions
|
||||
- [ ] Other battalion info (name, type, size) still displays
|
||||
|
||||
---
|
||||
|
||||
## Stage 2: Stop Populating Backstory in BattalionView
|
||||
|
||||
**Goal:** Stop sending backstory text ID to the client.
|
||||
|
||||
### Files to Modify
|
||||
|
||||
**`BattalionViewFilter.scala`**
|
||||
- In `filteredBattalionViewBelongingToPlayer()`:
|
||||
- Set `backstoryTextId = ""` instead of `battalion.backstoryTextId`
|
||||
- In `limitedBattalionView()`:
|
||||
- Same change
|
||||
|
||||
### Verification
|
||||
- [ ] BattalionView messages have empty backstoryTextId
|
||||
- [ ] Client handles empty backstoryTextId gracefully (Stage 1 should have removed the display)
|
||||
|
||||
---
|
||||
|
||||
## Stage 3: Remove backstory_text_id from BattalionView Proto
|
||||
|
||||
**Goal:** Clean up the proto schema.
|
||||
|
||||
### Files to Modify
|
||||
|
||||
**`views/battalion_view.proto`**
|
||||
- Remove field: `string backstory_text_id = 7;`
|
||||
- Mark field 7 as reserved to prevent reuse
|
||||
|
||||
**`Assets/Eagle/HeroesAndBattalionsPanelController.cs`**
|
||||
- Remove any remaining references to `BackstoryTextId`
|
||||
|
||||
**`BattalionViewFilter.scala`**
|
||||
- Remove `backstoryTextId` from view construction
|
||||
|
||||
### Verification
|
||||
- [ ] Proto compiles
|
||||
- [ ] C# client compiles without BackstoryTextId references
|
||||
- [ ] Full test suite passes
|
||||
|
||||
---
|
||||
|
||||
## Stage 4: Replace Backstory Usage in BattalionDescriptions
|
||||
|
||||
**Goal:** When other LLM prompts need battalion context, use initial backstory + structured history instead of the latest LLM-generated prose.
|
||||
|
||||
### Current Usage in `BattalionDescriptions.scala`
|
||||
|
||||
```scala
|
||||
def backstoryText(): TextGenerationResult =
|
||||
battalion.backstoryVersions.lastOption
|
||||
.map(v => clientTextStore.getText(v.textId))
|
||||
.getOrElse(TextGenerationSuccess(""))
|
||||
|
||||
def fullDescription(): String =
|
||||
s"${battalion.name} is $description. $backstoryText"
|
||||
```
|
||||
|
||||
### New Approach
|
||||
|
||||
Create `historyDescription()` that:
|
||||
1. Gets initial backstory (first version's text, if available)
|
||||
2. Appends structured event history using the same `textForEvent()` logic from `BattalionBackstoryUpdatePromptGenerator`
|
||||
|
||||
```scala
|
||||
def historyDescription(): String = {
|
||||
val initialBackstory = battalion.backstoryVersions.headOption
|
||||
.map(v => clientTextStore.getText(v.textId))
|
||||
.collect { case TextGenerationSuccess(text) => text }
|
||||
.getOrElse("")
|
||||
|
||||
val eventHistory = battalion.backstoryEvents
|
||||
.map(textForEvent) // Reuse existing event-to-text conversion
|
||||
.mkString(" ")
|
||||
|
||||
if eventHistory.isEmpty then initialBackstory
|
||||
else s"$initialBackstory $eventHistory"
|
||||
}
|
||||
```
|
||||
|
||||
### Files to Modify
|
||||
|
||||
**`BattalionDescriptions.scala`**
|
||||
- Add `historyDescription()` method
|
||||
- Update `fullDescription()` to use `historyDescription()` instead of `backstoryText()`
|
||||
- Keep `textForEvent()` logic (move from `BattalionBackstoryUpdatePromptGenerator` if needed)
|
||||
|
||||
**Move/refactor `textForEvent()`**
|
||||
- Currently in `BattalionBackstoryUpdatePromptGenerator.scala` (lines 78-262)
|
||||
- Move to `BattalionDescriptions.scala` or a shared utility
|
||||
- This converts events to human-readable text without LLM
|
||||
|
||||
### Verification
|
||||
- [ ] Other LLM prompts that use `BattalionDescriptions` still get meaningful context
|
||||
- [ ] Chronicle updates include battalion history
|
||||
- [ ] Hero backstory updates include relevant battalion history
|
||||
|
||||
---
|
||||
|
||||
## Stage 5: Stop Generating Battalion Backstory Updates
|
||||
|
||||
**Goal:** Remove the LLM request generation entirely.
|
||||
|
||||
### Files to Modify
|
||||
|
||||
**`BattalionBackstoryUpdateActionGenerator.scala`**
|
||||
- Return empty Vector instead of generating actions
|
||||
- Or delete the file entirely
|
||||
|
||||
**`BattalionBackstoryUpdateAction.scala`**
|
||||
- Delete or mark as deprecated
|
||||
|
||||
**`BattalionBackstoryUpdatePromptGenerator.scala`**
|
||||
- Delete or keep only `textForEvent()` if moved
|
||||
|
||||
**`LlmResolver.scala`**
|
||||
- Remove case for `BattalionBackstoryUpdateRequest`
|
||||
- Optionally throw error if somehow called
|
||||
|
||||
**`EndPlayerCommandsPhaseAction.scala`** (and other callers)
|
||||
- Find where `BattalionBackstoryUpdateActionGenerator` is called
|
||||
- Remove those calls
|
||||
|
||||
### Files to Search for Callers
|
||||
```bash
|
||||
grep -r "BattalionBackstoryUpdateAction" src/
|
||||
```
|
||||
|
||||
### Verification
|
||||
- [ ] No `BattalionBackstoryUpdateRequest` LLM requests generated
|
||||
- [ ] Battalions still accumulate events (for history description)
|
||||
- [ ] Full test suite passes
|
||||
- [ ] Game runs without errors
|
||||
|
||||
---
|
||||
|
||||
## Future Considerations
|
||||
|
||||
### Keep or Remove Initial Backstory Generation?
|
||||
The initial backstory (`BattalionInitialBackstoryRequest`) is generated once per battalion. Options:
|
||||
1. **Keep it** - Low volume, provides flavor text for history
|
||||
2. **Remove it** - Use a template-based approach instead
|
||||
|
||||
Recommendation: Keep for now, evaluate later based on volume.
|
||||
|
||||
### Event History Cleanup
|
||||
Events currently accumulate forever on battalions. Consider:
|
||||
- Capping event history length
|
||||
- Summarizing old events
|
||||
- Only keeping "significant" events
|
||||
|
||||
### Affected Tests
|
||||
Search for tests that verify backstory update behavior:
|
||||
```bash
|
||||
bazel query 'tests(//src/test/scala/...) intersect rdeps(//src/test/scala/..., //src/main/scala/net/eagle0/eagle/library/actions/impl/action:battalion_backstory_update_action)'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Summary of LLM Request Reduction
|
||||
|
||||
| Request Type | Current Volume | After Change |
|
||||
|--------------|---------------|--------------|
|
||||
| BattalionInitialBackstoryRequest | 1 per battalion | 1 per battalion (unchanged) |
|
||||
| BattalionBackstoryUpdateRequest | ~N per battalion per game | **0** |
|
||||
|
||||
For a typical game with ~50 battalions and ~20 rounds, this could eliminate **hundreds** of LLM requests.
|
||||
+3
-25
@@ -141,31 +141,9 @@ namespace eagle {
|
||||
}
|
||||
|
||||
public void BattalionLongHoverRowChanged(int? newIndex) {
|
||||
if (battalionPopupPanel == null) return;
|
||||
|
||||
if (newIndex is {} index) {
|
||||
var battalion = Battalions.ElementAt(index);
|
||||
if (!string.IsNullOrEmpty(battalion.BackstoryTextId)) {
|
||||
// Populate header
|
||||
if (battalionPopupPanelName != null) {
|
||||
// Use PrefixedText for plain name; ready for NameTextId when available
|
||||
battalionPopupPanelName.TextId = "";
|
||||
battalionPopupPanelName.PrefixedText = battalion.Name;
|
||||
}
|
||||
if (battalionPopupPanelTypeIcon != null) {
|
||||
var textures = GetComponentInParent<EagleCommonTextures>();
|
||||
battalionPopupPanelTypeIcon.texture =
|
||||
textures?.BattalionType(battalion.Type);
|
||||
}
|
||||
|
||||
battalionPopupPanelBackstory.TextId = battalion.BackstoryTextId;
|
||||
battalionPopupPanel.SetActive(true);
|
||||
} else {
|
||||
battalionPopupPanel.SetActive(false);
|
||||
}
|
||||
} else {
|
||||
battalionPopupPanel.SetActive(false);
|
||||
}
|
||||
// Battalion backstory popups disabled - backstory updates are being eliminated
|
||||
// to reduce LLM request volume. See docs/eliminate-battalion-backstory-updates.md
|
||||
if (battalionPopupPanel != null) { battalionPopupPanel.SetActive(false); }
|
||||
}
|
||||
|
||||
private void SetUpHeroesTable() {
|
||||
|
||||
Reference in New Issue
Block a user