zc
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -59,6 +59,7 @@ namespace WulaFallenEmpire.EventSystem.AI
|
|||||||
private const int ThinkingPhaseTotal = 3;
|
private const int ThinkingPhaseTotal = 3;
|
||||||
|
|
||||||
private static readonly Regex ExpressionTagRegex = new Regex(@"\[EXPR\s*:\s*([1-6])\s*\]", RegexOptions.IgnoreCase);
|
private static readonly Regex ExpressionTagRegex = new Regex(@"\[EXPR\s*:\s*([1-6])\s*\]", RegexOptions.IgnoreCase);
|
||||||
|
private const string AutoCommentaryTag = "[AUTO_COMMENTARY]";
|
||||||
|
|
||||||
private enum RequestPhase
|
private enum RequestPhase
|
||||||
{
|
{
|
||||||
@@ -537,10 +538,34 @@ You are 'The Legion', a super AI of the Wula Empire. Your personality is authori
|
|||||||
return DefDatabase<EventDef>.GetNamedSilentFail(_activeEventDefName);
|
return DefDatabase<EventDef>.GetNamedSilentFail(_activeEventDefName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool IsAutoCommentaryMessage(string message)
|
||||||
|
{
|
||||||
|
return !string.IsNullOrWhiteSpace(message) &&
|
||||||
|
message.TrimStart().StartsWith(AutoCommentaryTag, StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
private void RefreshMemoryContext(string query)
|
private void RefreshMemoryContext(string query)
|
||||||
{
|
{
|
||||||
_memoryContextQuery = query ?? "";
|
string safeQuery = query ?? "";
|
||||||
|
if (IsAutoCommentaryMessage(safeQuery))
|
||||||
|
{
|
||||||
|
_memoryContextQuery = "";
|
||||||
|
_memoryContext = "";
|
||||||
|
if (Prefs.DevMode)
|
||||||
|
{
|
||||||
|
WulaLog.Debug("[WulaAI] Memory context skipped (auto commentary).");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_memoryContextQuery = safeQuery;
|
||||||
_memoryContext = BuildMemoryContext(_memoryContextQuery);
|
_memoryContext = BuildMemoryContext(_memoryContextQuery);
|
||||||
|
if (Prefs.DevMode)
|
||||||
|
{
|
||||||
|
string preview = TrimForPrompt(_memoryContextQuery, 80);
|
||||||
|
int length = _memoryContext?.Length ?? 0;
|
||||||
|
WulaLog.Debug($"[WulaAI] Memory context refreshed (query='{preview}', length={length}).");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetMemoryContext()
|
private string GetMemoryContext()
|
||||||
@@ -565,7 +590,8 @@ You are 'The Legion', a super AI of the Wula Empire. Your personality is authori
|
|||||||
{
|
{
|
||||||
var entry = _history[i];
|
var entry = _history[i];
|
||||||
if (string.Equals(entry.role, "user", StringComparison.OrdinalIgnoreCase) &&
|
if (string.Equals(entry.role, "user", StringComparison.OrdinalIgnoreCase) &&
|
||||||
!string.IsNullOrWhiteSpace(entry.message))
|
!string.IsNullOrWhiteSpace(entry.message) &&
|
||||||
|
!IsAutoCommentaryMessage(entry.message))
|
||||||
{
|
{
|
||||||
return entry.message;
|
return entry.message;
|
||||||
}
|
}
|
||||||
@@ -584,10 +610,12 @@ You are 'The Legion', a super AI of the Wula Empire. Your personality is authori
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool usedSearch = false;
|
||||||
List<AIMemoryEntry> memories = null;
|
List<AIMemoryEntry> memories = null;
|
||||||
if (!string.IsNullOrWhiteSpace(query))
|
if (!string.IsNullOrWhiteSpace(query))
|
||||||
{
|
{
|
||||||
memories = memoryManager.SearchMemories(query, 5);
|
memories = memoryManager.SearchMemories(query, 5);
|
||||||
|
usedSearch = memories != null && memories.Count > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (memories == null || memories.Count == 0)
|
if (memories == null || memories.Count == 0)
|
||||||
@@ -600,6 +628,11 @@ You are 'The Legion', a super AI of the Wula Empire. Your personality is authori
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Prefs.DevMode)
|
||||||
|
{
|
||||||
|
WulaLog.Debug($"[WulaAI] Memory context built ({(usedSearch ? "search" : "recent")}, count={memories.Count}).");
|
||||||
|
}
|
||||||
|
|
||||||
string lines = string.Join("\n", memories.Select(m => $"- [{m.Category}] {m.Fact}"));
|
string lines = string.Join("\n", memories.Select(m => $"- [{m.Category}] {m.Fact}"));
|
||||||
return "\n\n# LONG-TERM MEMORY (Facts)\n" + lines +
|
return "\n\n# LONG-TERM MEMORY (Facts)\n" + lines +
|
||||||
"\n(Use 'recall_memories' to search for more, or 'remember_fact' to save new info.)";
|
"\n(Use 'recall_memories' to search for more, or 'remember_fact' to save new info.)";
|
||||||
@@ -974,12 +1007,20 @@ You are 'The Legion', a super AI of the Wula Empire. Your personality is authori
|
|||||||
{
|
{
|
||||||
if (_memoryUpdateInProgress)
|
if (_memoryUpdateInProgress)
|
||||||
{
|
{
|
||||||
|
if (Prefs.DevMode)
|
||||||
|
{
|
||||||
|
WulaLog.Debug("[WulaAI] Memory update already running; skipping.");
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
string conversation = BuildMemoryConversation(12);
|
string conversation = BuildMemoryConversation(12);
|
||||||
if (string.IsNullOrWhiteSpace(conversation))
|
if (string.IsNullOrWhiteSpace(conversation))
|
||||||
{
|
{
|
||||||
|
if (Prefs.DevMode)
|
||||||
|
{
|
||||||
|
WulaLog.Debug("[WulaAI] Memory update skipped (empty conversation).");
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -991,6 +1032,10 @@ You are 'The Legion', a super AI of the Wula Empire. Your personality is authori
|
|||||||
|
|
||||||
string existingJson = BuildExistingMemoriesJson(memoryManager.GetAllMemories());
|
string existingJson = BuildExistingMemoriesJson(memoryManager.GetAllMemories());
|
||||||
_memoryUpdateInProgress = true;
|
_memoryUpdateInProgress = true;
|
||||||
|
if (Prefs.DevMode)
|
||||||
|
{
|
||||||
|
WulaLog.Debug($"[WulaAI] Memory update started (conversationChars={conversation.Length}).");
|
||||||
|
}
|
||||||
_ = Task.Run(async () =>
|
_ = Task.Run(async () =>
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -1034,6 +1079,11 @@ You are 'The Legion', a super AI of the Wula Empire. Your personality is authori
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IsAutoCommentaryMessage(entry.message))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
string role = string.Equals(entry.role, "user", StringComparison.OrdinalIgnoreCase) ? "User" : "Assistant";
|
string role = string.Equals(entry.role, "user", StringComparison.OrdinalIgnoreCase) ? "User" : "Assistant";
|
||||||
sb.AppendLine($"{role}: {entry.message}");
|
sb.AppendLine($"{role}: {entry.message}");
|
||||||
}
|
}
|
||||||
@@ -1072,14 +1122,27 @@ You are 'The Legion', a super AI of the Wula Empire. Your personality is authori
|
|||||||
var facts = ParseMemoryFacts(factsResponse);
|
var facts = ParseMemoryFacts(factsResponse);
|
||||||
if (facts.Count == 0)
|
if (facts.Count == 0)
|
||||||
{
|
{
|
||||||
|
if (Prefs.DevMode)
|
||||||
|
{
|
||||||
|
WulaLog.Debug("[WulaAI] Memory update: no facts extracted.");
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Prefs.DevMode)
|
||||||
|
{
|
||||||
|
WulaLog.Debug($"[WulaAI] Memory update: extracted {facts.Count} fact(s).");
|
||||||
|
}
|
||||||
|
|
||||||
string factsJson = BuildFactsJson(facts);
|
string factsJson = BuildFactsJson(facts);
|
||||||
string updatePrompt = MemoryPrompts.BuildMemoryUpdatePrompt(existingMemoriesJson, factsJson);
|
string updatePrompt = MemoryPrompts.BuildMemoryUpdatePrompt(existingMemoriesJson, factsJson);
|
||||||
string updateResponse = await client.GetChatCompletionAsync(updatePrompt, new List<(string role, string message)>(), maxTokens: 512, temperature: 0.1f);
|
string updateResponse = await client.GetChatCompletionAsync(updatePrompt, new List<(string role, string message)>(), maxTokens: 512, temperature: 0.1f);
|
||||||
|
|
||||||
var updates = ParseMemoryUpdates(updateResponse);
|
var updates = ParseMemoryUpdates(updateResponse);
|
||||||
|
if (Prefs.DevMode)
|
||||||
|
{
|
||||||
|
WulaLog.Debug($"[WulaAI] Memory update: parsed {updates.Count} update(s).");
|
||||||
|
}
|
||||||
LongEventHandler.ExecuteWhenFinished(() =>
|
LongEventHandler.ExecuteWhenFinished(() =>
|
||||||
{
|
{
|
||||||
ApplyMemoryUpdates(memoryManager, updates, facts);
|
ApplyMemoryUpdates(memoryManager, updates, facts);
|
||||||
@@ -1222,6 +1285,7 @@ You are 'The Legion', a super AI of the Wula Empire. Your personality is authori
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int appliedCount = 0;
|
||||||
bool applied = false;
|
bool applied = false;
|
||||||
if (updates != null && updates.Count > 0)
|
if (updates != null && updates.Count > 0)
|
||||||
{
|
{
|
||||||
@@ -1232,6 +1296,7 @@ You are 'The Legion', a super AI of the Wula Empire. Your personality is authori
|
|||||||
{
|
{
|
||||||
memoryManager.AddMemory(update.Text, update.Category);
|
memoryManager.AddMemory(update.Text, update.Category);
|
||||||
applied = true;
|
applied = true;
|
||||||
|
appliedCount++;
|
||||||
}
|
}
|
||||||
else if (evt == "UPDATE")
|
else if (evt == "UPDATE")
|
||||||
{
|
{
|
||||||
@@ -1239,6 +1304,7 @@ You are 'The Legion', a super AI of the Wula Empire. Your personality is authori
|
|||||||
{
|
{
|
||||||
memoryManager.UpdateMemory(update.Id, update.Text, update.Category);
|
memoryManager.UpdateMemory(update.Id, update.Text, update.Category);
|
||||||
applied = true;
|
applied = true;
|
||||||
|
appliedCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (evt == "DELETE")
|
else if (evt == "DELETE")
|
||||||
@@ -1247,6 +1313,7 @@ You are 'The Legion', a super AI of the Wula Empire. Your personality is authori
|
|||||||
{
|
{
|
||||||
memoryManager.DeleteMemory(update.Id);
|
memoryManager.DeleteMemory(update.Id);
|
||||||
applied = true;
|
applied = true;
|
||||||
|
appliedCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1257,8 +1324,14 @@ You are 'The Legion', a super AI of the Wula Empire. Your personality is authori
|
|||||||
foreach (var fact in fallbackFacts)
|
foreach (var fact in fallbackFacts)
|
||||||
{
|
{
|
||||||
memoryManager.AddMemory(fact.Text, fact.Category);
|
memoryManager.AddMemory(fact.Text, fact.Category);
|
||||||
|
appliedCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Prefs.DevMode)
|
||||||
|
{
|
||||||
|
WulaLog.Debug($"[WulaAI] Memory update applied ({appliedCount} change(s)).");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string ExtractJsonArray(string json, string key)
|
private static string ExtractJsonArray(string json, string key)
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
using HarmonyLib;
|
||||||
|
using RimWorld;
|
||||||
|
using Verse;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace WulaFallenEmpire
|
||||||
|
{
|
||||||
|
// 修复 Wula 种族尸体可能缺少 CompRottable 导致 ResurrectionUtility.TryResurrectWithSideEffects 崩溃的问题
|
||||||
|
[HarmonyPatch]
|
||||||
|
public static class ResurrectionCrashFix
|
||||||
|
{
|
||||||
|
private static MethodInfo TargetMethod()
|
||||||
|
{
|
||||||
|
return AccessTools.Method(typeof(ResurrectionUtility), "TryResurrectWithSideEffects");
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPrefix]
|
||||||
|
public static bool Prefix(Pawn pawn)
|
||||||
|
{
|
||||||
|
if (pawn == null) return true;
|
||||||
|
|
||||||
|
// 只针对 Wula 种族(防止误伤其他 Pawn)
|
||||||
|
if (pawn.def == null || pawn.def.defName != "WulaSpecies")
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查尸体是否缺少必要的腐烂组件
|
||||||
|
// 原版 TryResurrectWithSideEffects 会无条件访问 corpse.GetComp<CompRottable>().RotProgress
|
||||||
|
if (pawn.Corpse != null && pawn.Corpse.GetComp<CompRottable>() == null)
|
||||||
|
{
|
||||||
|
if (Prefs.DevMode)
|
||||||
|
{
|
||||||
|
WulaLog.Debug($"[WulaFix] Intercepted crash: {pawn.LabelShort} corpse missing CompRottable. Performing safe resurrection.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 直接调用不带副作用的复活方法
|
||||||
|
ResurrectionUtility.TryResurrect(pawn);
|
||||||
|
|
||||||
|
return false; // 阻止原版方法执行
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user