87 lines
2.8 KiB
Python
87 lines
2.8 KiB
Python
"""手工测试 AI API 连接;自动测试导入本模块时不会发起请求。"""
|
|
|
|
import unittest
|
|
from unittest import mock
|
|
|
|
import requests
|
|
|
|
from ai_chat import _post_with_retry, get_ai_reply
|
|
|
|
|
|
def main() -> None:
|
|
import os
|
|
import sys
|
|
import traceback
|
|
|
|
sys.path.insert(0, os.path.dirname(__file__))
|
|
|
|
from ai_config import AI_API_BASE, AI_API_KEY, AI_MODEL
|
|
from ai_chat import _completions_url, call_ai_text
|
|
|
|
print(f"API 地址: {AI_API_BASE}")
|
|
print(f"模型名称: {AI_MODEL}")
|
|
print(f"API Key: {'已配置' if AI_API_KEY else '未配置'}(不会显示密钥)")
|
|
print(f"请求 URL: {_completions_url()}")
|
|
print("-" * 40)
|
|
print("正在发送测试消息...")
|
|
|
|
try:
|
|
reply = call_ai_text("你好")
|
|
print(f"\n[+] AI 回复: {reply}")
|
|
print("\n测试通过!AI 模型可以正常使用。")
|
|
except Exception as exc:
|
|
print(f"\n[-] 测试失败: {exc}")
|
|
response = getattr(exc, "response", None)
|
|
if response is not None:
|
|
print(f"状态码: {response.status_code}")
|
|
print(f"响应体: {response.text[:500]}")
|
|
traceback.print_exc()
|
|
|
|
|
|
class ManualAIIsolationTest(unittest.TestCase):
|
|
def test_manual_entrypoint_is_import_safe(self) -> None:
|
|
self.assertTrue(callable(main))
|
|
|
|
def test_transient_model_failure_is_retried_once(self) -> None:
|
|
response = mock.Mock(status_code=200)
|
|
with (
|
|
mock.patch(
|
|
"ai_chat._SESSION.post",
|
|
side_effect=[requests.exceptions.Timeout(), response],
|
|
) as post,
|
|
mock.patch("ai_chat.time.sleep"),
|
|
):
|
|
result = _post_with_retry(
|
|
"https://example.invalid/v1/chat/completions",
|
|
purpose="测试模型",
|
|
timeout=1,
|
|
)
|
|
self.assertIs(result, response)
|
|
self.assertEqual(post.call_count, 2)
|
|
|
|
def test_authentication_failure_is_not_retried(self) -> None:
|
|
response = mock.Mock(status_code=401)
|
|
with mock.patch("ai_chat._SESSION.post", return_value=response) as post:
|
|
result = _post_with_retry(
|
|
"https://example.invalid/v1/chat/completions",
|
|
purpose="测试模型",
|
|
timeout=1,
|
|
)
|
|
self.assertIs(result, response)
|
|
post.assert_called_once()
|
|
|
|
def test_final_timeout_keeps_a_specific_chain_error(self) -> None:
|
|
with (
|
|
mock.patch(
|
|
"ai_chat.call_ai_text",
|
|
side_effect=requests.exceptions.Timeout(),
|
|
),
|
|
mock.patch("ai_chat.time.sleep"),
|
|
):
|
|
with self.assertRaisesRegex(RuntimeError, "模型链路超时"):
|
|
get_ai_reply(chat_text="测试")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|