refactor to reorganise codebase
This commit is contained in:
99
chatmock/upstream.py
Normal file
99
chatmock/upstream.py
Normal file
@@ -0,0 +1,99 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import time
|
||||
from typing import Any, Dict, List, Tuple
|
||||
|
||||
import requests
|
||||
from flask import Response, jsonify, make_response
|
||||
|
||||
from .config import CHATGPT_RESPONSES_URL
|
||||
from .http import build_cors_headers
|
||||
from .utils import get_effective_chatgpt_auth
|
||||
|
||||
|
||||
def normalize_model_name(name: str | None, debug_model: str | None = None) -> str:
|
||||
if isinstance(debug_model, str) and debug_model.strip():
|
||||
return debug_model.strip()
|
||||
if not isinstance(name, str) or not name.strip():
|
||||
return "gpt-5"
|
||||
base = name.split(":", 1)[0].strip()
|
||||
mapping = {
|
||||
"gpt5": "gpt-5",
|
||||
"gpt-5-latest": "gpt-5",
|
||||
"gpt-5": "gpt-5",
|
||||
"codex": "codex-mini-latest",
|
||||
"codex-mini": "codex-mini-latest",
|
||||
"codex-mini-latest": "codex-mini-latest",
|
||||
}
|
||||
return mapping.get(base, base)
|
||||
|
||||
|
||||
def start_upstream_request(
|
||||
model: str,
|
||||
input_items: List[Dict[str, Any]],
|
||||
*,
|
||||
instructions: str | None = None,
|
||||
tools: List[Dict[str, Any]] | None = None,
|
||||
tool_choice: Any | None = None,
|
||||
parallel_tool_calls: bool = False,
|
||||
reasoning_param: Dict[str, Any] | None = None,
|
||||
):
|
||||
access_token, account_id = get_effective_chatgpt_auth()
|
||||
if not access_token or not account_id:
|
||||
resp = make_response(
|
||||
jsonify(
|
||||
{
|
||||
"error": {
|
||||
"message": "Missing ChatGPT credentials. Run 'python3 chatmock.py login' first.",
|
||||
}
|
||||
}
|
||||
),
|
||||
401,
|
||||
)
|
||||
for k, v in build_cors_headers().items():
|
||||
resp.headers.setdefault(k, v)
|
||||
return None, resp
|
||||
|
||||
include: List[str] = []
|
||||
if isinstance(reasoning_param, dict) and reasoning_param.get("effort") != "none":
|
||||
include.append("reasoning.encrypted_content")
|
||||
|
||||
responses_payload = {
|
||||
"model": model,
|
||||
"instructions": instructions if isinstance(instructions, str) and instructions.strip() else instructions,
|
||||
"input": input_items,
|
||||
"tools": tools or [],
|
||||
"tool_choice": tool_choice if tool_choice in ("auto", "none") or isinstance(tool_choice, dict) else "auto",
|
||||
"parallel_tool_calls": bool(parallel_tool_calls),
|
||||
"store": False,
|
||||
"stream": True,
|
||||
"include": include,
|
||||
}
|
||||
|
||||
if reasoning_param is not None:
|
||||
responses_payload["reasoning"] = reasoning_param
|
||||
|
||||
headers = {
|
||||
"Authorization": f"Bearer {access_token}",
|
||||
"Content-Type": "application/json",
|
||||
"Accept": "text/event-stream",
|
||||
"chatgpt-account-id": account_id,
|
||||
"OpenAI-Beta": "responses=experimental",
|
||||
}
|
||||
|
||||
try:
|
||||
upstream = requests.post(
|
||||
CHATGPT_RESPONSES_URL,
|
||||
headers=headers,
|
||||
json=responses_payload,
|
||||
stream=True,
|
||||
timeout=600,
|
||||
)
|
||||
except requests.RequestException as e:
|
||||
resp = make_response(jsonify({"error": {"message": f"Upstream ChatGPT request failed: {e}"}}), 502)
|
||||
for k, v in build_cors_headers().items():
|
||||
resp.headers.setdefault(k, v)
|
||||
return None, resp
|
||||
return upstream, None
|
||||
|
||||
Reference in New Issue
Block a user