fix: omit responses reasoning context
This commit is contained in:
parent
8ed5939ebb
commit
27b1891f1c
|
|
@ -62,9 +62,6 @@ pub(crate) struct ResponsesRequest {
|
|||
pub(crate) struct ReasoningConfig {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub effort: Option<String>,
|
||||
/// API 側の reasoning retention policy。Insomnia はこの値を送るが、
|
||||
/// persisted reasoning item の client-side filtering はしない。
|
||||
pub context: &'static str,
|
||||
/// summary の出力制御。`"auto"` 固定で summary_text を受け取る。
|
||||
pub summary: &'static str,
|
||||
}
|
||||
|
|
@ -196,7 +193,6 @@ impl OpenAIResponsesScheme {
|
|||
ReasoningControl::Effort(effort) => Some(effort.as_str().to_string()),
|
||||
ReasoningControl::BudgetTokens(_) => None,
|
||||
},
|
||||
context: "current_turn",
|
||||
summary: "auto",
|
||||
})
|
||||
.filter(|reasoning| reasoning.effort.is_some());
|
||||
|
|
@ -507,7 +503,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn current_turn_reasoning_is_kept_across_function_call_loop() {
|
||||
fn reasoning_is_kept_across_function_call_loop() {
|
||||
let scheme = OpenAIResponsesScheme::new();
|
||||
let req = Request::new()
|
||||
.user("run tool")
|
||||
|
|
@ -523,18 +519,6 @@ mod tests {
|
|||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reasoning_request_uses_current_turn_context() {
|
||||
let scheme = OpenAIResponsesScheme::new();
|
||||
let mut req = Request::new().user("hi");
|
||||
req.config.reasoning = Some(ReasoningControl::Effort(ReasoningEffort::Medium));
|
||||
let body = scheme.build_request("gpt-5", &req, &cap_with_reasoning());
|
||||
let reasoning = body.reasoning.expect("reasoning should be set");
|
||||
assert_eq!(reasoning.context, "current_turn");
|
||||
let json = serde_json::to_value(reasoning).unwrap();
|
||||
assert_eq!(json["context"], "current_turn");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reasoning_summary_field_is_always_serialized() {
|
||||
// Responses API は reasoning item に `summary` を必須で要求する。
|
||||
|
|
@ -566,8 +550,12 @@ mod tests {
|
|||
let body = scheme.build_request("gpt-5", &req, &cap_with_reasoning());
|
||||
let reasoning = body.reasoning.expect("reasoning should be set");
|
||||
assert_eq!(reasoning.effort.as_deref(), Some("high"));
|
||||
assert_eq!(reasoning.context, "current_turn");
|
||||
assert_eq!(reasoning.summary, "auto");
|
||||
let json = serde_json::to_value(reasoning).unwrap();
|
||||
assert!(
|
||||
json.get("context").is_none(),
|
||||
"reasoning.context must not be serialized, got: {json}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -289,11 +289,6 @@ fn request_body_shape_payload(body: &Value) -> Value {
|
|||
json!(reasoning_encrypted_content_bytes),
|
||||
);
|
||||
}
|
||||
let reasoning_context = body
|
||||
.get("reasoning")
|
||||
.and_then(|reasoning| reasoning.get("context"))
|
||||
.and_then(Value::as_str);
|
||||
map.insert("reasoning_context".to_string(), json!(reasoning_context));
|
||||
Value::Object(map)
|
||||
}
|
||||
|
||||
|
|
@ -683,7 +678,7 @@ mod tests {
|
|||
#[test]
|
||||
fn request_body_shape_counts_reasoning_encrypted_content() {
|
||||
let payload = request_body_shape_payload(&json!({
|
||||
"reasoning": { "context": "current_turn" },
|
||||
"reasoning": { "summary": "auto" },
|
||||
"input": [
|
||||
{ "type": "message", "role": "user", "content": [] },
|
||||
{ "type": "reasoning", "encrypted_content": "abc", "summary": [] },
|
||||
|
|
@ -694,7 +689,6 @@ mod tests {
|
|||
assert_eq!(payload["reasoning_items"], 2);
|
||||
assert_eq!(payload["reasoning_encrypted_content_count"], 2);
|
||||
assert_eq!(payload["reasoning_encrypted_content_bytes"], 8);
|
||||
assert_eq!(payload["reasoning_context"], "current_turn");
|
||||
assert!(payload["items_json_bytes"].as_u64().unwrap() > 0);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ reasoning トークンは各ターンの後に破棄される。次ターンに
|
|||
1. `previous_response_id` パラメータで過去のレスポンスを参照
|
||||
2. `response.output` の全アイテムを次の `input` に手動で渡す
|
||||
|
||||
ステートレス利用(`store=false`、ZDR組織)の場合は `include=["reasoning.encrypted_content"]` を指定すれば暗号化された推論コンテンツを受け取り、次リクエストに渡すことで推論を引き継げる。Insomnia は Responses リクエストに `reasoning.context="current_turn"` を明示するが、このパラメータの正確な履歴境界 semantics は provider 側の責務として扱い、履歴から復元した reasoning item を client 側でターン境界に基づいて削除しない。
|
||||
ステートレス利用(`store=false`、ZDR組織)の場合は `include=["reasoning.encrypted_content"]` を指定すれば暗号化された推論コンテンツを受け取り、次リクエストに渡すことで推論を引き継げる。Insomnia は履歴から復元した reasoning item を通常の API message として扱い、独自の turn-boundary filtering はしない。
|
||||
|
||||
同一ターン内の function-call loop でも、`reasoning item → function_call → function_call_output → 次の Responses request` の連続性を保つため、履歴上の reasoning item は通常の API message として保持する。ToolResult は wire 上で user 側 item に見えるが、reasoning item の削除境界としては扱わない。
|
||||
|
||||
|
|
@ -187,7 +187,7 @@ Ollamaはローカル実行プラットフォームで、モデルごとに思
|
|||
|
||||
**ChatGPT を使うとき**
|
||||
- 新規実装は **Responses API** を選ぶ(Chat Completions は推論引き継ぎが弱い)
|
||||
- ZDR組織でも `reasoning.encrypted_content` で推論を引き継げる。Insomnia は `reasoning.context="current_turn"` を送るが、履歴上の reasoning item は通常の API message として扱い、独自の turn-boundary filtering はしない
|
||||
- ZDR組織でも `reasoning.encrypted_content` で推論を引き継げる。履歴上の reasoning item は通常の API message として扱い、独自の turn-boundary filtering はしない
|
||||
- raw reasoning の抽出を試みない(規約違反の可能性)
|
||||
|
||||
**Ollama を使うとき**
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user