refactor : FastAPI 懒加载单例,消除模块级副作用
- import astrai.inference 不再在模块加载时创建 FastAPI 实例 - 路由移至 APIRouter;get_app() 首次调用时懒构造单例 - _create_engine 和 run_server 的 param_path 改为必填 - 更新测试改用 get_app() 替代模块级 app
This commit is contained in:
@@ -5,21 +5,22 @@ from unittest.mock import MagicMock
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from astrai.inference import app
|
||||
from astrai.inference import get_app
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def client():
|
||||
"""Provide a test client for the FastAPI app."""
|
||||
app.state.server_config = {
|
||||
_app = get_app()
|
||||
_app.state.server_config = {
|
||||
"device": "cpu",
|
||||
"dtype": "bfloat16",
|
||||
"param_path": None,
|
||||
"max_batch_size": 1,
|
||||
"_test": True,
|
||||
}
|
||||
app.state.engine = None
|
||||
return TestClient(app)
|
||||
_app.state.engine = None
|
||||
return TestClient(_app)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -49,5 +50,5 @@ def mock_engine():
|
||||
@pytest.fixture
|
||||
def loaded_model(client, mock_engine):
|
||||
"""Simulate that the engine is loaded."""
|
||||
app.state.engine = mock_engine
|
||||
get_app().state.engine = mock_engine
|
||||
return mock_engine
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
import pytest
|
||||
|
||||
from astrai.inference import app
|
||||
from astrai.inference import get_app
|
||||
|
||||
|
||||
def test_health_no_model(client):
|
||||
"""GET /health should return 200 even when engine not loaded."""
|
||||
app.state.engine = None
|
||||
get_app().state.engine = None
|
||||
response = client.get("/health")
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
@@ -30,7 +30,7 @@ def test_chat_completions_non_stream(client, loaded_model):
|
||||
async def async_gen():
|
||||
yield "Assistant reply"
|
||||
|
||||
app.state.engine = loaded_model
|
||||
get_app().state.engine = loaded_model
|
||||
loaded_model.generate_async.return_value = async_gen()
|
||||
response = client.post(
|
||||
"/v1/chat/completions",
|
||||
@@ -56,7 +56,7 @@ def test_chat_completions_stream(client, loaded_model):
|
||||
yield "cumulative1"
|
||||
yield "cumulative2"
|
||||
|
||||
app.state.engine = loaded_model
|
||||
get_app().state.engine = loaded_model
|
||||
loaded_model.generate_async.return_value = async_gen()
|
||||
response = client.post(
|
||||
"/v1/chat/completions",
|
||||
@@ -83,7 +83,7 @@ def test_messages_non_stream(client, loaded_model):
|
||||
async def async_gen():
|
||||
yield "Assistant reply"
|
||||
|
||||
app.state.engine = loaded_model
|
||||
get_app().state.engine = loaded_model
|
||||
loaded_model.generate_async.return_value = async_gen()
|
||||
response = client.post(
|
||||
"/v1/messages",
|
||||
@@ -111,7 +111,7 @@ def test_messages_stream(client, loaded_model):
|
||||
yield "cumulative1"
|
||||
yield "cumulative2"
|
||||
|
||||
app.state.engine = loaded_model
|
||||
get_app().state.engine = loaded_model
|
||||
loaded_model.generate_async.return_value = async_gen()
|
||||
response = client.post(
|
||||
"/v1/messages",
|
||||
@@ -141,7 +141,7 @@ def test_messages_with_system(client, loaded_model):
|
||||
async def async_gen():
|
||||
yield "Reply"
|
||||
|
||||
app.state.engine = loaded_model
|
||||
get_app().state.engine = loaded_model
|
||||
loaded_model.generate_async.return_value = async_gen()
|
||||
response = client.post(
|
||||
"/v1/messages",
|
||||
@@ -165,7 +165,7 @@ def test_chat_completions_stop_sequence(client, loaded_model):
|
||||
yield "X"
|
||||
yield "world"
|
||||
|
||||
app.state.engine = loaded_model
|
||||
get_app().state.engine = loaded_model
|
||||
loaded_model.generate_async.return_value = async_gen()
|
||||
response = client.post(
|
||||
"/v1/chat/completions",
|
||||
@@ -191,7 +191,7 @@ def test_chat_completions_stop_sequence_stream(client, loaded_model):
|
||||
yield "X"
|
||||
yield "world"
|
||||
|
||||
app.state.engine = loaded_model
|
||||
get_app().state.engine = loaded_model
|
||||
loaded_model.generate_async.return_value = async_gen()
|
||||
response = client.post(
|
||||
"/v1/chat/completions",
|
||||
|
||||
Reference in New Issue
Block a user