修复: AI上下文邻接性收口 + 设置页i18n缺失键
- df-ai 三元组邻接性收口: sanitize/openai_compat 闭合判定由「id 全局存在」收紧为「紧后 tool 连续段覆盖」,夹层序列(后台压缩/用户插话楔入)不再直送 provider 致 400 insufficient tool messages - 设置页补 settings.loading 缺失键(zh/en),修版本信息返回前渲染字面串 - 看板: 907 接手核查补注(实现口径=剥除非归位,有损)+ 遗留登记 909 + 908 销账
This commit is contained in:
@@ -372,18 +372,34 @@ fn extract_tool_call_ids(msg: &OpenAiMessage) -> Vec<String> {
|
||||
fn sanitize_openai_triplets(messages: &mut Vec<OpenAiMessage>) {
|
||||
use std::collections::HashSet;
|
||||
|
||||
// step 1:resolved_ids = 所有 tool 消息提供的 tool_call_id(有 result 响应的 id)。
|
||||
let resolved_ids: HashSet<String> = messages
|
||||
.iter()
|
||||
.filter(|m| m.role == "tool")
|
||||
.filter_map(|m| m.tool_call_id.clone())
|
||||
.collect();
|
||||
// step 1:相邻性判定的依据 = 每个 assistant 头「紧后 tool 连续段」覆盖的 id 集合。
|
||||
// 根因(2026-10-09):原实现按「id 全局存在」判闭合(位置无关),而 OpenAI 协议要求
|
||||
// tool 响应必须**紧随**其 assistant(tool_calls)。后台压缩摘要在 head 已 push、tool
|
||||
// 结果未 push 的窗口内可楔入 system(context_lifecycle),被隔开的响应仍被判"已闭合"
|
||||
// → 畸形序列放行 → 上游 400「insufficient tool messages」。故判定口径由「id 全局存在」
|
||||
// 收紧为「紧后连续段覆盖」:未覆盖的 call 视同未闭合剥除,其游离响应随后由 step3 丢弃。
|
||||
let mut adjacency: std::collections::HashMap<usize, HashSet<String>> =
|
||||
std::collections::HashMap::new();
|
||||
for i in 0..messages.len() {
|
||||
if messages[i].role != "assistant" {
|
||||
continue;
|
||||
}
|
||||
let mut seg: HashSet<String> = HashSet::new();
|
||||
let mut j = i + 1;
|
||||
while j < messages.len() && messages[j].role == "tool" {
|
||||
if let Some(id) = messages[j].tool_call_id.as_deref() {
|
||||
seg.insert(id.to_string());
|
||||
}
|
||||
j += 1;
|
||||
}
|
||||
adjacency.insert(i, seg);
|
||||
}
|
||||
|
||||
let mut stripped_heads = 0u32;
|
||||
let mut total_stripped = 0u32;
|
||||
|
||||
// step 2:assistant 剥未闭合 tool_call(无对应 tool result 响应)。
|
||||
for m in messages.iter_mut() {
|
||||
// step 2:assistant 剥未闭合 tool_call(其响应不在紧后连续段内)。
|
||||
for (i, m) in messages.iter_mut().enumerate() {
|
||||
if m.role != "assistant" {
|
||||
continue;
|
||||
}
|
||||
@@ -393,12 +409,13 @@ fn sanitize_openai_triplets(messages: &mut Vec<OpenAiMessage>) {
|
||||
if calls.is_empty() {
|
||||
continue;
|
||||
}
|
||||
let seg = adjacency.get(&i);
|
||||
let kept: Vec<serde_json::Value> = calls
|
||||
.iter()
|
||||
.filter(|tc| {
|
||||
tc.get("id")
|
||||
.and_then(|v| v.as_str())
|
||||
.is_some_and(|id| resolved_ids.contains(id))
|
||||
.is_some_and(|id| seg.is_some_and(|s| s.contains(id)))
|
||||
})
|
||||
.cloned()
|
||||
.collect();
|
||||
|
||||
Reference in New Issue
Block a user