From f33a6829e8b94805fd06a3af9200031e4a83eb89 Mon Sep 17 00:00:00 2001 From: lanyizi Date: Sun, 23 Aug 2026 22:34:30 +0200 Subject: [PATCH] =?UTF-8?q?=E5=B0=9D=E8=AF=95=E9=87=8D=E6=96=B0=E6=80=9D?= =?UTF-8?q?=E8=80=83=E5=BE=97=E6=9B=B4=E7=9F=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AIChatPanel.xaml.cs | 57 ++++- AIProviderSettingsControl.xaml | 23 +- AIProviderSettingsControl.xaml.cs | 21 ++ AI_REASONING_CONTINUATION_RESEARCH.md | 12 + AiV2.Tests/Program.cs | 324 +++++++++++++++++++++++- PLAN_ai_analysis_v2.md | 8 + Utils/AIAnalyze.cs | 348 ++++++++++++++++++++++++-- Utils/AiReasoningGuard.cs | 181 ++++++++++++++ Utils/AiSettings.cs | 11 + 9 files changed, 960 insertions(+), 25 deletions(-) create mode 100644 Utils/AiReasoningGuard.cs diff --git a/AIChatPanel.xaml.cs b/AIChatPanel.xaml.cs index 832f91b..e6ef214 100644 --- a/AIChatPanel.xaml.cs +++ b/AIChatPanel.xaml.cs @@ -364,6 +364,7 @@ namespace AnotherReplayReader OnChunk, _linkedCts.Token); UpdateTokenDisplay(overviewResult); + ReportReasoningGuardResult(overviewResult); _overview = OverviewParser.Parse(overviewResult.Response); _overviewNarrative = _overview.Narrative; AppendLog( @@ -490,6 +491,7 @@ namespace AnotherReplayReader OnChunk, _linkedCts.Token); UpdateTokenDisplay(segmentResult); + ReportReasoningGuardResult(segmentResult); segmentResponse = segmentResult.Response; if (backqueryCount >= maxBackqueriesPerSegment) @@ -582,6 +584,7 @@ namespace AnotherReplayReader _suppressDisplay = false; } UpdateTokenDisplay(revisionResult); + ReportReasoningGuardResult(revisionResult); if (string.IsNullOrWhiteSpace(revisionResult.Response)) { @@ -675,6 +678,7 @@ namespace AnotherReplayReader _linkedCts.Token); UpdateTokenDisplay(result); + ReportReasoningGuardResult(result); // 总结轮回查:允许模型请求一次远处原始区间,作为同一会话的追加输入。 if (_replayData is null) @@ -727,6 +731,7 @@ namespace AnotherReplayReader OnChunk, _linkedCts.Token); UpdateTokenDisplay(finalSummary); + ReportReasoningGuardResult(finalSummary); AppendLog("总结完成", "已根据回查区间补充最终总结。", false); } @@ -752,7 +757,9 @@ namespace AnotherReplayReader var total = 0; foreach (var message in messages) { - total += AiContextBudget.EstimateTokens(message.Content); + total += AiContextBudget.EstimateTokens(message.Content ?? string.Empty); + total += AiContextBudget.EstimateTokens( + message.ReasoningContent ?? string.Empty); } var check = AiContextBudget.CheckRequestUsage( total, requestContext.Provider, requestContext.Model); @@ -806,6 +813,44 @@ namespace AnotherReplayReader _chunkQueue.Enqueue((chunk, DateTimeOffset.UtcNow)); } + private void ReportReasoningGuardResult(AIAnalyze.Result result) + { + if (!result.ReasoningInterrupted + && !result.ContinuationApplied + && string.IsNullOrWhiteSpace(result.ReasoningContinuationError)) + { + return; + } + + if (!string.IsNullOrWhiteSpace(result.ReasoningContinuationError)) + { + AppendLog("推理保护警告", result.ReasoningContinuationError, false); + } + else if (result.ContinuationApplied) + { + AppendLog("推理保护", "已请求 AI 尽快收尾,并完成最终回答。", false); + } + else if (result.ReasoningInterrupted) + { + AppendLog("推理保护", "检测到推理内容超限,正在处理续写结果。", false); + } + + if (!string.IsNullOrWhiteSpace(result.ReasoningOriginalRequestJson)) + { + AppendLog( + "推理保护:首次请求消息", + result.ReasoningOriginalRequestJson, + true); + } + if (!string.IsNullOrWhiteSpace(result.ReasoningContinuationRequestJson)) + { + AppendLog( + "推理保护:续写请求完整消息", + result.ReasoningContinuationRequestJson, + true); + } + } + private void StartThinkingBlock() { _thinkingStartTime = DateTime.Now; @@ -1035,6 +1080,7 @@ namespace AnotherReplayReader var thinkSb = new StringBuilder(); var contentSb = new StringBuilder(); var errorSb = new StringBuilder(); + var guardTriggered = false; while (_chunkQueue.TryDequeue(out var data)) { var (chunk, time) = data; @@ -1062,6 +1108,11 @@ namespace AnotherReplayReader { errorSb.AppendLine(chunk.Text); } + else if (chunk.Type == AIAnalyze.AIChunkType.ReasoningGuard) + { + EndThinkingBlock(); + guardTriggered = true; + } } if (thinkSb.Length > 0) @@ -1080,6 +1131,10 @@ namespace AnotherReplayReader { AddErrorBlock(errorSb.ToString()); } + if (guardTriggered) + { + _currentContent = null; + } } private void AutoScroll() diff --git a/AIProviderSettingsControl.xaml b/AIProviderSettingsControl.xaml index 96be9b2..74bb221 100644 --- a/AIProviderSettingsControl.xaml +++ b/AIProviderSettingsControl.xaml @@ -143,6 +143,7 @@ + @@ -164,20 +165,34 @@ Content="支持 SSE 流式输出" Margin="0,5"/> -