添加修改模型请求头

This commit is contained in:
h88782481 2026-03-13 20:25:33 +08:00
parent 406a36af89
commit e726f11bad
9 changed files with 109 additions and 1 deletions

View file

@ -137,6 +137,8 @@ def add_mapping():
'api_key': data.get('api_key', ''),
'custom_instructions': data.get('custom_instructions', ''),
'instructions_position': data.get('instructions_position', 'prepend'),
'body_modifications': data.get('body_modifications') or {},
'header_modifications': data.get('header_modifications') or {},
}
return _save_and_respond(s, f'映射已添加: {name}')
@ -161,6 +163,8 @@ def update_mapping(name):
'api_key': data.get('api_key', ''),
'custom_instructions': data.get('custom_instructions', ''),
'instructions_position': data.get('instructions_position', 'prepend'),
'body_modifications': data.get('body_modifications') or {},
'header_modifications': data.get('header_modifications') or {},
}
if new_name != name:
del mappings[name]

View file

@ -28,6 +28,8 @@ from adapters.responses_cc_adapter import (
from config import Config
from routes.common import (
RouteContext,
apply_body_modifications,
apply_header_modifications,
build_anthropic_target,
build_openai_target,
build_responses_target,
@ -118,6 +120,8 @@ def _handle_openai_backend(ctx: RouteContext, payload: dict[str, Any]):
)
url, headers = build_openai_target(ctx)
payload = apply_body_modifications(payload, ctx.body_modifications)
headers = apply_header_modifications(headers, ctx.header_modifications)
if ctx.is_stream:
return _handle_openai_stream(ctx, payload, url, headers)
@ -208,6 +212,8 @@ def _handle_responses_backend(ctx: RouteContext, payload: dict[str, Any]):
)
url, headers = build_responses_target(ctx)
responses_payload = apply_body_modifications(responses_payload, ctx.body_modifications)
headers = apply_header_modifications(headers, ctx.header_modifications)
if ctx.is_stream:
return _handle_responses_stream(ctx, responses_payload, url, headers)
@ -285,6 +291,8 @@ def _handle_anthropic_backend(ctx: RouteContext, payload: dict[str, Any]):
)
url, headers = build_anthropic_target(ctx)
anthropic_payload = apply_body_modifications(anthropic_payload, ctx.body_modifications)
headers = apply_header_modifications(headers, ctx.header_modifications)
if ctx.is_stream:
return _handle_anthropic_stream(ctx, anthropic_payload, url, headers)

View file

@ -34,6 +34,8 @@ class RouteContext:
is_stream: bool
custom_instructions: str
instructions_position: str
body_modifications: dict
header_modifications: dict
def build_route_context(client_model: str, is_stream: bool) -> RouteContext:
@ -48,6 +50,8 @@ def build_route_context(client_model: str, is_stream: bool) -> RouteContext:
is_stream=is_stream,
custom_instructions=mapping.get('custom_instructions', ''),
instructions_position=mapping.get('instructions_position', 'prepend'),
body_modifications=mapping.get('body_modifications', {}),
header_modifications=mapping.get('header_modifications', {}),
)
@ -193,3 +197,38 @@ def inject_instructions_anthropic(payload: dict[str, Any], instructions: str, po
logger.info('已注入自定义指令到 Anthropic system (%d 字符, %s)', len(instructions), position)
return payload
# ─── Body / Header 修改 ──────────────────────────
def apply_body_modifications(payload: dict[str, Any], modifications: dict[str, Any]) -> dict[str, Any]:
"""对转发请求体应用字段级修改。
规则与 CursorProxy 一致值为 null 的字段会被删除其余字段设置/覆盖
"""
if not modifications:
return payload
for key, value in modifications.items():
if value is None:
payload.pop(key, None)
else:
payload[key] = value
logger.info('已应用 body_modifications: %s', list(modifications.keys()))
return payload
def apply_header_modifications(headers: dict[str, str], modifications: dict[str, Any]) -> dict[str, str]:
"""对转发请求头应用字段级修改。
规则同 body值为 null 删除其余设置/覆盖
"""
if not modifications:
return headers
for key, value in modifications.items():
if value is None:
headers.pop(key, None)
else:
headers[key] = str(value)
logger.info('已应用 header_modifications: %s', list(modifications.keys()))
return headers

View file

@ -13,7 +13,7 @@ from flask import Blueprint, request, jsonify
import settings
from config import Config
from routes.common import inject_instructions_anthropic
from routes.common import apply_body_modifications, apply_header_modifications, inject_instructions_anthropic
from utils.http import build_anthropic_headers, forward_request, sse_response
logger = logging.getLogger(__name__)
@ -35,10 +35,14 @@ def messages_passthrough():
api_key = mapping['api_key']
custom_instructions = mapping.get('custom_instructions', '')
instructions_position = mapping.get('instructions_position', 'prepend')
body_mods = mapping.get('body_modifications', {})
header_mods = mapping.get('header_modifications', {})
headers = build_anthropic_headers(api_key)
headers = apply_header_modifications(headers, header_mods)
url = f'{url_base.rstrip("/")}/v1/messages'
payload = inject_instructions_anthropic(payload, custom_instructions, instructions_position)
payload = apply_body_modifications(payload, body_mods)
if not is_stream:
resp, err = forward_request(url, headers, payload)

View file

@ -18,6 +18,8 @@ from adapters.responses_cc_adapter import ResponsesStreamConverter, cc_to_respon
from config import Config
from routes.common import (
RouteContext,
apply_body_modifications,
apply_header_modifications,
build_anthropic_target,
build_openai_target,
build_responses_target,
@ -93,6 +95,8 @@ def _handle_openai_backend(ctx: RouteContext, cc_payload: dict[str, Any]):
)
url, headers = build_openai_target(ctx)
cc_payload = apply_body_modifications(cc_payload, ctx.body_modifications)
headers = apply_header_modifications(headers, ctx.header_modifications)
if ctx.is_stream:
return _handle_openai_stream(ctx, cc_payload, url, headers)
@ -177,6 +181,8 @@ def _handle_responses_backend(ctx: RouteContext, payload: dict[str, Any]):
payload['model'] = ctx.upstream_model
payload = inject_instructions_responses(payload, ctx.custom_instructions, ctx.instructions_position)
url, headers = build_responses_target(ctx)
payload = apply_body_modifications(payload, ctx.body_modifications)
headers = apply_header_modifications(headers, ctx.header_modifications)
if ctx.is_stream:
return _handle_responses_stream(ctx, payload, url, headers)
@ -241,6 +247,8 @@ def _handle_anthropic_backend(ctx: RouteContext, cc_payload: dict[str, Any]):
)
url, headers = build_anthropic_target(ctx)
anthropic_payload = apply_body_modifications(anthropic_payload, ctx.body_modifications)
headers = apply_header_modifications(headers, ctx.header_modifications)
if ctx.is_stream:
return _handle_anthropic_stream(ctx, anthropic_payload, url, headers)