"""手工测试 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()