Files
EvoScientist/scripts/test_gpt55_connection.py
T
m4 c2743251e9 Initial commit of EvoScientist framework
Self-evolving AI scientist framework built on LangGraph/LangChain with
CLI/TUI core, FastAPI gateway, and Next.js frontend.

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
2026-07-13 08:07:45 +08:00

616 lines
19 KiB
Python

#!/usr/bin/env python3
"""Standalone gpt-5.5 endpoint diagnostics.
This script intentionally stays outside the gateway/agent runtime. It checks:
1. structured config resolution for gpt-5.5
2. raw OpenAI-compatible Chat Completions
3. raw OpenAI Responses API
4. LangChain direct chat/responses clients
5. optional EvoScientist get_chat_model app path
It never prints API keys.
"""
from __future__ import annotations
import argparse
import asyncio
import json
import os
import traceback
import time
from pathlib import Path
from typing import Any
import httpx
from openai import AsyncOpenAI, DefaultAsyncHttpxClient
from langchain.chat_models import init_chat_model
from langchain_core.messages import HumanMessage
def _load_dotenv_file(path: Path) -> None:
if not path.exists():
return
for raw in path.read_text(encoding="utf-8").splitlines():
line = raw.strip()
if not line or line.startswith("#") or "=" not in line:
continue
key, value = line.split("=", 1)
key = key.strip()
value = value.strip().strip('"').strip("'")
os.environ.setdefault(key, value)
def _short_body(text: str, limit: int = 500) -> str:
text = text.replace("\n", " ").replace("\r", " ")
if len(text) <= limit:
return text
return text[:limit] + "...<truncated>"
def _json_safe(value: Any) -> str:
try:
return json.dumps(value, ensure_ascii=False, default=str)
except Exception:
return repr(value)
def _print_result(label: str, status: int | str, elapsed: float, body: str) -> None:
print(f"[{label}] status={status} elapsed={elapsed:.2f}s body={_short_body(body)}")
def _post_json(
client: httpx.Client,
label: str,
url: str,
api_key: str,
payload: dict[str, Any],
) -> None:
headers = {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"}
start = time.perf_counter()
try:
resp = client.post(url, headers=headers, json=payload)
elapsed = time.perf_counter() - start
_print_result(label, resp.status_code, elapsed, resp.text)
except Exception as exc:
elapsed = time.perf_counter() - start
_print_result(label, type(exc).__name__, elapsed, str(exc))
def _get(
client: httpx.Client,
label: str,
url: str,
api_key: str,
) -> None:
headers = {"Authorization": f"Bearer {api_key}"}
start = time.perf_counter()
try:
resp = client.get(url, headers=headers)
elapsed = time.perf_counter() - start
_print_result(label, resp.status_code, elapsed, resp.text)
except Exception as exc:
elapsed = time.perf_counter() - start
_print_result(label, type(exc).__name__, elapsed, str(exc))
async def _try_langchain(
label: str,
*,
model: str,
api_key: str,
base_url: str,
use_responses_api: bool,
max_tokens: int,
reasoning: dict[str, Any] | None = None,
) -> None:
kwargs: dict[str, Any] = {
"model": model,
"model_provider": "openai",
"api_key": api_key,
"base_url": base_url,
"use_responses_api": use_responses_api,
"max_tokens": max_tokens,
"request_timeout": 30,
"stream_usage": True,
}
if reasoning is not None:
kwargs["reasoning"] = reasoning
start = time.perf_counter()
try:
llm = init_chat_model(**kwargs)
payload = llm._get_request_payload(
[HumanMessage(content="Say OK in one word.")], stop=None
)
print(f"[{label}] payload={_json_safe(payload)}")
msg = await llm.ainvoke([HumanMessage(content="Say OK in one word.")])
elapsed = time.perf_counter() - start
body = _json_safe(
{
"content": msg.content,
"usage": getattr(msg, "usage_metadata", None),
}
)
_print_result(label, "OK", elapsed, body)
except Exception as exc:
elapsed = time.perf_counter() - start
_print_result(label, type(exc).__name__, elapsed, str(exc))
async def _try_openai_sdk(
label: str,
*,
model: str,
api_key: str,
base_url: str,
mode: str,
max_tokens: int,
sanitize_headers: bool = False,
) -> None:
async def on_request(request: httpx.Request) -> None:
if sanitize_headers:
for key in list(request.headers):
lower_key = key.lower()
if lower_key.startswith("x-stainless-") and lower_key != "x-stainless-raw-response":
request.headers.pop(key, None)
request.headers["User-Agent"] = "python-httpx"
headers = {
k: v
for k, v in request.headers.items()
if k.lower()
not in {
"authorization",
"cookie",
"x-api-key",
}
}
print(
f"[{label}] request method={request.method} url={request.url} "
f"headers={_json_safe(headers)}"
)
http_client = DefaultAsyncHttpxClient(
timeout=30.0,
event_hooks={"request": [on_request]},
)
client = AsyncOpenAI(
api_key=api_key,
base_url=base_url,
timeout=30.0,
max_retries=0,
http_client=http_client,
)
start = time.perf_counter()
try:
if mode == "chat":
result = await client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": "Say OK in one word."}],
max_completion_tokens=max_tokens,
)
body = result.model_dump()
elif mode == "responses":
result = await client.responses.create(
model=model,
input=[
{
"role": "user",
"content": "Say OK in one word.",
"type": "message",
}
],
max_output_tokens=max_tokens,
)
body = result.model_dump()
else:
raise ValueError(f"unknown mode: {mode}")
elapsed = time.perf_counter() - start
_print_result(label, "OK", elapsed, _json_safe(body))
except Exception as exc:
elapsed = time.perf_counter() - start
_print_result(label, type(exc).__name__, elapsed, str(exc))
finally:
await http_client.aclose()
async def _try_app_path(model: str) -> None:
from EvoScientist.config.settings import apply_config_to_env, load_config
from EvoScientist.llm.models import _clear_structured_config_cache, get_chat_model
apply_config_to_env(load_config())
_clear_structured_config_cache()
start = time.perf_counter()
try:
llm = get_chat_model(model)
payload = llm._get_request_payload(
[HumanMessage(content="Say OK in one word.")], stop=None
)
print(f"[app:get_chat_model] payload={_json_safe(payload)}")
msg = await llm.ainvoke([HumanMessage(content="Say OK in one word.")])
elapsed = time.perf_counter() - start
body = _json_safe(
{
"content": msg.content,
"usage": getattr(msg, "usage_metadata", None),
"use_responses_api": getattr(llm, "use_responses_api", None),
"base_url": getattr(llm, "openai_api_base", None),
}
)
_print_result("app:get_chat_model", "OK", elapsed, body)
except Exception as exc:
elapsed = time.perf_counter() - start
cause = repr(getattr(exc, "__cause__", None))
context = repr(getattr(exc, "__context__", None))
_print_result(
"app:get_chat_model",
type(exc).__name__,
elapsed,
f"{exc} cause={cause} context={context}",
)
traceback.print_exception(type(exc), exc, exc.__traceback__, limit=6)
def _resolve_config(model_ref: str) -> tuple[str, str, str, dict[str, Any]]:
from EvoScientist.config.model_config import load_structured_config, resolve_model
from EvoScientist.config.settings import apply_config_to_env, load_config
apply_config_to_env(load_config())
cfg = load_structured_config()
resolved = resolve_model(model_ref, config=cfg)
api_key = resolved.api_key.strip() if resolved.api_key else ""
base_url = resolved.base_url.rstrip("/")
print(
"[config] "
f"provider={resolved.provider_name} protocol={resolved.protocol} "
f"model={resolved.model_id} base_url={base_url} "
f"api_key_set={bool(api_key)} params={_json_safe(resolved.params)}"
)
print(
"[env] "
f"EVOSCIENTIST_USE_RESPONSES_API="
f"{os.environ.get('EVOSCIENTIST_USE_RESPONSES_API')!r}"
)
return resolved.model_id, api_key, base_url, resolved.params
async def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--model", default="gpt-5.5")
parser.add_argument("--timeout", type=float, default=30.0)
parser.add_argument("--max-tokens", type=int, default=128)
parser.add_argument("--full-app-path", action="store_true")
parser.add_argument(
"--case",
choices=(
"all",
"raw-chat-exact",
"raw-chat-sdk-headers",
"raw-chat-sanitized-sdk-headers",
"raw-chat-accept-json",
"raw-chat-user-agent",
"raw-responses-exact",
"sdk-chat",
"sdk-chat-sanitized",
"sdk-responses",
"sdk-responses-sanitized",
"app",
),
default="all",
help="Run a single diagnostic case to avoid triggering provider cooldowns.",
)
args = parser.parse_args()
_load_dotenv_file(Path(".env"))
model_id, api_key, base_url, _params = _resolve_config(args.model)
if not api_key:
print("[fatal] API key is empty after config resolution")
return 2
if not base_url:
print("[fatal] base_url is empty after config resolution")
return 2
chat_payload = {
"model": model_id,
"messages": [{"role": "user", "content": "Say OK in one word."}],
"max_tokens": args.max_tokens,
}
responses_payload = {
"model": model_id,
"input": "Say OK in one word.",
"max_output_tokens": args.max_tokens,
}
lc_chat_payload = {
"model": model_id,
"messages": [{"role": "user", "content": "Say OK in one word."}],
"max_completion_tokens": args.max_tokens,
"stream": False,
}
lc_responses_payload = {
"model": model_id,
"input": [
{
"role": "user",
"content": "Say OK in one word.",
"type": "message",
}
],
"max_output_tokens": args.max_tokens,
"stream": False,
}
if args.case == "raw-chat-exact":
with httpx.Client(timeout=args.timeout) as client:
_post_json(
client,
"raw:POST /chat/completions exact-lc",
f"{base_url}/chat/completions",
api_key,
lc_chat_payload,
)
return 0
if args.case == "raw-chat-sdk-headers":
headers = {
"Authorization": f"Bearer {api_key}",
"Accept": "application/json",
"Content-Type": "application/json",
"User-Agent": "AsyncOpenAI/Python 2.31.0",
"X-Stainless-Lang": "python",
"X-Stainless-Package-Version": "2.31.0",
"X-Stainless-OS": "Linux",
"X-Stainless-Arch": "x64",
"X-Stainless-Runtime": "CPython",
"X-Stainless-Runtime-Version": "3.12.13",
"X-Stainless-Async": "async:asyncio",
"X-Stainless-Retry-Count": "0",
"X-Stainless-Read-Timeout": "30.0",
}
start = time.perf_counter()
try:
with httpx.Client(timeout=args.timeout) as client:
resp = client.post(
f"{base_url}/chat/completions",
headers=headers,
json=lc_chat_payload,
)
elapsed = time.perf_counter() - start
_print_result(
"raw:POST /chat/completions sdk-headers",
resp.status_code,
elapsed,
resp.text,
)
except Exception as exc:
elapsed = time.perf_counter() - start
_print_result(
"raw:POST /chat/completions sdk-headers",
type(exc).__name__,
elapsed,
str(exc),
)
return 0
if args.case == "raw-chat-sanitized-sdk-headers":
headers = {
"Authorization": f"Bearer {api_key}",
"Accept": "application/json",
"Content-Type": "application/json",
"User-Agent": "python-httpx",
}
start = time.perf_counter()
try:
with httpx.Client(timeout=args.timeout) as client:
resp = client.post(
f"{base_url}/chat/completions",
headers=headers,
json=lc_chat_payload,
)
elapsed = time.perf_counter() - start
_print_result(
"raw:POST /chat/completions sanitized-sdk-headers",
resp.status_code,
elapsed,
resp.text,
)
except Exception as exc:
elapsed = time.perf_counter() - start
_print_result(
"raw:POST /chat/completions sanitized-sdk-headers",
type(exc).__name__,
elapsed,
str(exc),
)
return 0
if args.case in ("raw-chat-accept-json", "raw-chat-user-agent"):
headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
}
if args.case == "raw-chat-accept-json":
headers["Accept"] = "application/json"
label = "raw:POST /chat/completions accept-json"
else:
headers["User-Agent"] = "python-httpx"
label = "raw:POST /chat/completions user-agent"
start = time.perf_counter()
try:
with httpx.Client(timeout=args.timeout) as client:
resp = client.post(
f"{base_url}/chat/completions",
headers=headers,
json=lc_chat_payload,
)
elapsed = time.perf_counter() - start
_print_result(label, resp.status_code, elapsed, resp.text)
except Exception as exc:
elapsed = time.perf_counter() - start
_print_result(label, type(exc).__name__, elapsed, str(exc))
return 0
if args.case == "raw-responses-exact":
with httpx.Client(timeout=args.timeout) as client:
_post_json(
client,
"raw:POST /responses exact-lc",
f"{base_url}/responses",
api_key,
lc_responses_payload,
)
return 0
if args.case == "sdk-chat":
await _try_openai_sdk(
"sdk:chat",
model=model_id,
api_key=api_key,
base_url=base_url,
mode="chat",
max_tokens=args.max_tokens,
)
return 0
if args.case == "sdk-chat-sanitized":
await _try_openai_sdk(
"sdk:chat:sanitized",
model=model_id,
api_key=api_key,
base_url=base_url,
mode="chat",
max_tokens=args.max_tokens,
sanitize_headers=True,
)
return 0
if args.case == "sdk-responses":
await _try_openai_sdk(
"sdk:responses",
model=model_id,
api_key=api_key,
base_url=base_url,
mode="responses",
max_tokens=args.max_tokens,
)
return 0
if args.case == "sdk-responses-sanitized":
await _try_openai_sdk(
"sdk:responses:sanitized",
model=model_id,
api_key=api_key,
base_url=base_url,
mode="responses",
max_tokens=args.max_tokens,
sanitize_headers=True,
)
return 0
if args.case == "app":
await _try_app_path(args.model)
return 0
with httpx.Client(timeout=args.timeout) as client:
_get(client, "raw:GET /v1/models", f"{base_url}/v1/models", api_key)
_post_json(
client,
"raw:POST /chat/completions",
f"{base_url}/chat/completions",
api_key,
chat_payload,
)
_post_json(
client,
"raw:POST /v1/chat/completions",
f"{base_url}/v1/chat/completions",
api_key,
chat_payload,
)
_post_json(
client,
"raw:POST /chat/completions exact-lc",
f"{base_url}/chat/completions",
api_key,
lc_chat_payload,
)
_post_json(
client,
"raw:POST /responses",
f"{base_url}/responses",
api_key,
responses_payload,
)
_post_json(
client,
"raw:POST /v1/responses",
f"{base_url}/v1/responses",
api_key,
responses_payload,
)
_post_json(
client,
"raw:POST /responses exact-lc",
f"{base_url}/responses",
api_key,
lc_responses_payload,
)
_post_json(
client,
"raw:POST /v1/responses exact-lc",
f"{base_url}/v1/responses",
api_key,
lc_responses_payload,
)
await _try_langchain(
"lc:chat",
model=model_id,
api_key=api_key,
base_url=base_url,
use_responses_api=False,
max_tokens=args.max_tokens,
)
await _try_langchain(
"lc:responses",
model=model_id,
api_key=api_key,
base_url=base_url,
use_responses_api=True,
max_tokens=args.max_tokens,
)
await _try_langchain(
"lc:responses+reasoning",
model=model_id,
api_key=api_key,
base_url=base_url,
use_responses_api=True,
max_tokens=args.max_tokens,
reasoning={"effort": "high", "summary": "auto"},
)
await _try_openai_sdk(
"sdk:chat",
model=model_id,
api_key=api_key,
base_url=base_url,
mode="chat",
max_tokens=args.max_tokens,
)
await _try_openai_sdk(
"sdk:responses",
model=model_id,
api_key=api_key,
base_url=base_url,
mode="responses",
max_tokens=args.max_tokens,
)
if args.full_app_path:
await _try_app_path(args.model)
return 0
if __name__ == "__main__":
raise SystemExit(asyncio.run(main()))