Spaces:
Running
Running
| from pathlib import Path | |
| from deep_learning.data.spec import TokenizerBundle | |
| from deep_learning.pipeline.impl.text_generation.pipeline import TextInferenceBundle | |
| from deep_learning.ui.gradio.text_app import TextGenerationAppBuilder | |
| from deep_learning.ui.gradio.text_deployment import ( | |
| load_poetry_gpt_deployment_inference_artifact, | |
| load_poetry_rnn_deployment_inference_artifact, | |
| load_wiki_gpt_deployment_inference_artifact | |
| ) | |
| class DummyModel: | |
| pass | |
| class DummyTokenizer: | |
| def vocabulary_size(self): | |
| return 32 | |
| class DummyInput: | |
| def __init__(self, hidden_dim: int): | |
| self.shape = (None, hidden_dim) | |
| class DummyStatefulModel: | |
| def __init__(self): | |
| self.inputs = [ | |
| DummyInput(1), | |
| DummyInput(16), | |
| DummyInput(16), | |
| DummyInput(16), | |
| DummyInput(16) | |
| ] | |
| class DummyCheckpointLoadRules: | |
| def __init__(self, checkpoint_dir: Path): | |
| self.checkpoint_dir = checkpoint_dir | |
| def resolve_test_rule(self, default_dirs): | |
| return { | |
| "dirs": [self.checkpoint_dir] | |
| } | |
| class DummyPipeline: | |
| def __init__(self, checkpoint_dir: Path): | |
| self.name = "test_text" | |
| self.checkpoint_dir = checkpoint_dir | |
| self.checkpoint_load_rules = DummyCheckpointLoadRules(checkpoint_dir) | |
| def _create_text_app_builder(tmp_path, load_inference_artifact, load_inference_resource=None): | |
| checkpoint_dir = tmp_path / "checkpoints" | |
| checkpoint_dir.mkdir() | |
| (checkpoint_dir / "model_epoch_001.keras").write_text("stub", encoding="utf-8") | |
| return TextGenerationAppBuilder( | |
| pipeline=DummyPipeline(checkpoint_dir), | |
| title="测试文本页面", | |
| load_inference_artifact=load_inference_artifact, | |
| load_inference_resource=load_inference_resource | |
| ) | |
| def _dummy_text_inference_bundle() -> TextInferenceBundle: | |
| return TextInferenceBundle( | |
| tokenizer_bundle=TokenizerBundle( | |
| tokenizer=lambda text: [], | |
| decode=lambda token_ids: "", | |
| end_of_text=99, | |
| vocab_size=32, | |
| vocab_path="saved/vocab/test.txt" | |
| ), | |
| docs_ds=None, | |
| max_length=16, | |
| sample_fn=None | |
| ) | |
| def test_text_app_builder_model_info_does_not_load_model(tmp_path): | |
| """验证文本页面展示模型信息时只读取推理资源,不加载完整模型。""" | |
| builder = _create_text_app_builder( | |
| tmp_path, | |
| lambda checkpoint_rule: (_ for _ in ()).throw(AssertionError("模型信息不应加载模型")), | |
| load_inference_resource=_dummy_text_inference_bundle | |
| ) | |
| model_info = builder.get_model_info() | |
| assert "model_epoch_001.keras" in model_info | |
| assert "saved/vocab/test.txt" in model_info | |
| def test_wiki_gpt_app_builder_loads_deployment_resource_without_training_data(tmp_path, monkeypatch): | |
| """验证 Wiki GPT 页面加载部署模型和仓库词表时不会读取训练数据。""" | |
| builder = _create_text_app_builder(tmp_path, load_wiki_gpt_deployment_inference_artifact) | |
| monkeypatch.setattr( | |
| "deep_learning.models.mini_gpt.model_builder.keras.models.load_model", | |
| lambda path, custom_objects: DummyModel() | |
| ) | |
| monkeypatch.setattr( | |
| "deep_learning.ui.gradio.text_deployment.sentence_piece", | |
| lambda: (DummyTokenizer(), 99, lambda token_ids: "") | |
| ) | |
| inference_artifact, resource = builder._load_inference_artifact() | |
| assert isinstance(inference_artifact.model, DummyModel) | |
| assert isinstance(resource, TextInferenceBundle) | |
| assert resource.tokenizer_bundle.vocab_path.endswith("saved/vocab/sentencepiece/vocabulary.proto") | |
| def test_poetry_gpt_app_builder_loads_deployment_resource_without_training_data(tmp_path, monkeypatch): | |
| """验证 Poetry GPT 页面加载部署模型和仓库词表时不会读取训练数据。""" | |
| builder = _create_text_app_builder(tmp_path, load_poetry_gpt_deployment_inference_artifact) | |
| monkeypatch.setattr( | |
| "deep_learning.models.mini_gpt.model_builder.keras.models.load_model", | |
| lambda path, custom_objects: DummyModel() | |
| ) | |
| inference_artifact, resource = builder._load_inference_artifact() | |
| assert isinstance(inference_artifact.model, DummyModel) | |
| assert isinstance(resource, TextInferenceBundle) | |
| assert resource.tokenizer_bundle.vocab_path.endswith("saved/vocab/poetry/vocab.txt") | |
| def test_poetry_rnn_app_builder_loads_deployment_resource_without_training_data(tmp_path, monkeypatch): | |
| """验证 Poetry RNN 页面加载部署模型和仓库词表时不会读取训练数据。""" | |
| builder = _create_text_app_builder(tmp_path, load_poetry_rnn_deployment_inference_artifact) | |
| monkeypatch.setattr( | |
| "deep_learning.models.rnn.keras.models.load_model", | |
| lambda path: DummyStatefulModel() | |
| ) | |
| inference_artifact, resource = builder._load_inference_artifact() | |
| assert isinstance(inference_artifact.model, DummyStatefulModel) | |
| assert isinstance(resource, TextInferenceBundle) | |
| assert resource.tokenizer_bundle.vocab_path.endswith("saved/vocab/poetry/vocab.txt") | |