| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- from __future__ import annotations
- from uuid import UUID, uuid4
- from core.models import Post
- from decode_content import gates
- from decode_content.contracts import load_decode_contracts
- from decode_content.models import ContractSnapshot, DecodeJob, DecodeResult, KnowledgeParticle, PayloadDraft, ReadResult, ScopeResult
- from decode_content.scoping import NORMALIZE
- from decode_content.service import DecodeService, slugify
- class FakeRepo:
- def __init__(self):
- self.jobs = []
- self.results = []
- self.particles = []
- self.scopes = []
- self.payloads = []
- self.snapshots = []
- def create_decode_job(self, *, item_id: UUID, status: str = "pending", metadata=None):
- job = DecodeJob(id=uuid4(), item_id=item_id, status=status, metadata=metadata or {})
- self.jobs.append(job)
- return job
- def save_decode_result(self, **kwargs):
- result = DecodeResult(id=uuid4(), **kwargs)
- self.results.append(result)
- return result
- def save_knowledge_particle(self, **kwargs):
- particle = KnowledgeParticle(id=uuid4(), **kwargs)
- self.particles.append(particle)
- return particle
- def save_scope_result(self, **kwargs):
- scope = ScopeResult(id=uuid4(), **kwargs)
- self.scopes.append(scope)
- return scope
- def save_payload_draft(self, **kwargs):
- payload = PayloadDraft(id=uuid4(), **kwargs)
- self.payloads.append(payload)
- return payload
- def save_contract_snapshot(self, **kwargs):
- snapshot = ContractSnapshot(id=uuid4(), **kwargs)
- self.snapshots.append(snapshot)
- return snapshot
- def test_slugify_formal_helper():
- assert slugify("分镜脚本") == "分镜脚本"
- assert slugify("A B!c") == "a-b-c"
- assert slugify("") == "run"
- def test_decode_service_short_circuits_empty_read():
- item_id = uuid4()
- repo = FakeRepo()
- service = DecodeService(repository=repo, reader=lambda post: ReadResult(is_empty=True))
- out = service.decode_post(item_id=item_id, post=Post(id="xhs_1", platform="xiaohongshu", url="u", content_id="1"))
- assert out.status == "skipped"
- assert repo.results[0].status == "skipped"
- assert repo.particles == []
- assert repo.snapshots
- def test_decode_service_full_flow_with_fake_llm():
- item_id = uuid4()
- repo = FakeRepo()
- contract = load_decode_contracts()
- def fake_chat(system, user, timeout=None):
- if system == gates.GATE_ADMIT:
- return {"in_scope": True}
- if system == gates.GATE_REFUTE:
- return {"out_of_scope": False}
- if system == gates.GATE_HOW_ADMIT:
- return {"is_real_how": True}
- if system == gates.GATE_HOW_REFUTE:
- return {"is_fake": False}
- if system == gates.GATE_WHY_REFUTE:
- return {"not_why": False}
- if system == NORMALIZE:
- return {"映射": {}}
- if system == contract.phase1:
- return {
- "knowledges": [
- {
- "id": "k1",
- "type": "how",
- "role": "主",
- "title": "脚本搭建流程",
- "purpose": "搭出脚本",
- "业务阶段": ["脚本"],
- "steps": [
- {
- "id": "s1",
- "input": "选题",
- "directive": "先定受众",
- "output": "受众画像",
- "创作阶段": "定向",
- }
- ],
- }
- ]
- }
- if system == contract.phase2:
- return {
- "scopes": [
- {
- "knowledge_id": "k1",
- "step_id": "s1",
- "items": [{"scope_type": "intent", "value": "吸引注意"}],
- }
- ]
- }
- raise AssertionError(system[:80])
- service = DecodeService(
- repository=repo,
- contract=contract,
- chat_json_fn=fake_chat,
- reader=lambda post: ReadResult(text="这是一条脚本创作知识"),
- )
- out = service.decode_post(
- item_id=item_id,
- post=Post(id="xhs_1", platform="xiaohongshu", url="u", content_id="1", title="脚本教程"),
- )
- assert out.status == "decoded"
- assert repo.results[0].status == "decoded"
- assert repo.particles[0].particle_type == "how"
- assert repo.scopes[0].scope_type == "intent"
- assert repo.payloads[0].payload["dim_attributes"] == ["how"]
- assert repo.snapshots[0].contract_name == "创作知识提取-skill"
|