搜索

PythonReactSEOPDF
GitHub Skill

impl-service

Implementar serviços de lógica de negócio em services/. Use quando criar service, lógica de negócio, orquestração de repositórios, ou integração com LLM.

ciandt-fulvio☆ 0 仓库 Stars0 仓库 Forks

安装与使用

请根据来源仓库和你的 AI 工具说明安装此技能。先阅读技能文件和依赖要求,再添加到工作流。

查看来源 ↗使用指南

技能说明

Implementar Service (Camada de Lógica de Negócio)

Regras Arquiteturais (NON-NEGOTIABLE)

  1. TODA lógica de negócio deve estar em services, NUNCA em routers ou repositories
  2. Validações de negócio (limites, regras, constraints) ficam no service
  3. Prompts de LLM ficam no service, NUNCA em routers
  4. Chamadas LLM DEVEM usar tracing Phoenix: _tracer.start_as_current_span()
  5. Dependency Injection: repositories são injetados no __init__
  6. Orquestração: services chamam repositories, NUNCA acessam DB diretamente
  7. Bloco de validação: todo service DEVE ter if __name__ == "__main__":

Estrutura de Arquivos

src/synth_lab/services/
├── {entity}_service.py      # Um arquivo por domínio
├── errors.py                 # Exceções de negócio
└── {feature}/                # Subpastas para features complexas
    ├── __init__.py
    └── {sub_service}.py

Convenções de nome:

  • Arquivo: {entity}_service.py (singular, snake_case)
  • Classe: {Entity}Service (PascalCase)
  • Métodos: {verbo}_{substantivo} (ex: create_experiment, list_synths)

Padrões de Código

Service Básico (sem LLM)
"""
{Entity} service for synth-lab.

Business logic layer for {entity} operations.
"""

from synth_lab.models.pagination import PaginatedResponse, PaginationParams
from synth_lab.repositories.{entity}_repository import {Entity}Repository


class {Entity}Service:
    """Service for {entity} business logic."""

    # Constantes de validação
    NAME_MAX_LENGTH = 100

    def __init__(self, repository: {Entity}Repository | None = None):
        """Initialize with dependency injection."""
        self.repository = repository or {Entity}Repository()

    def list_{entities}(
        self,
        params: PaginationParams | None = None,
    ) -> PaginatedResponse[{Entity}Summary]:
        """List {entities} with pagination."""
        params = params or PaginationParams()
        return self.repository.list_{entities}(params)

    def get_{entity}(self, {entity}_id: str) -> {Entity}Detail:
        """Get {entity} by ID."""
        return self.repository.get_by_id({entity}_id)

    def create_{entity}(self, name: str) -> {Entity}:
        """Create new {entity} with validation."""
        # Validação de negócio
        if not name or not name.strip():
            raise ValueError("name is required")
        if len(name) > self.NAME_MAX_LENGTH:
            raise ValueError(f"name exceeds {self.NAME_MAX_LENGTH} chars")

        # Criar e persistir
        entity = {Entity}(name=name.strip())
        return self.repository.create(entity)
Service com LLM
"""
{Feature} LLM service for synth-lab.

LLM-powered business logic.
"""

from loguru import logger

from synth_lab.infrastructure.llm_client import LLMClient, get_llm_client
from synth_lab.infrastructure.phoenix_tracing import get_tracer

_tracer = get_tracer("{feature}_service")


class {Feature}Service:
    """Service with LLM integration."""

    def __init__(self, llm_client: LLMClient | None = None):
        self.llm = llm_client or get_llm_client()
        self.logger = logger.bind(component="{feature}_service")

    def generate(self, data: InputData) -> Result:
        """Generate result using LLM."""
        with _tracer.start_as_current_span("generate"):
            prompt = self._build_prompt(data)
            response = self.llm.complete_json(
                messages=[{"role": "user", "content": prompt}],
                operation_name="generate_result",
            )
            self.logger.info(f"Generated for {data.id}")
            return self._parse_response(response)

    def _build_prompt(self, data: InputData) -> str:
        """Build LLM prompt (private method)."""
        return f"""
        Instrução: ...
        Dados: {data.model_dump_json()}
        """

    def _parse_response(self, response: dict) -> Result:
        """Parse and validate LLM response."""
        return Result(**response)
Bloco de Validação (OBRIGATÓRIO)
if __name__ == "__main__":
    import sys

    from synth_lab.infrastructure.config import DB_PATH
    from synth_lab.infrastructure.database import DatabaseManager

    all_validation_failures = []
    total_tests = 0

    if not DB_PATH.exists():
        print(f"Database not found at {DB_PATH}")
        sys.exit(1)

    db = DatabaseManager(DB_PATH)
    service = {Entity}Service()

    # Test 1: Operação básica
    total_tests += 1
    try:
        result = service.list_{entities}()
        if result.pagination.total < 0:
            all_validation_failures.append("Invalid total")
    except Exception as e:
        all_validation_failures.append(f"List failed: {e}")

    # Test 2: Validação de erro
    total_tests += 1
    try:
        service.get_{entity}("invalid_id")
        all_validation_failures.append("Should raise NotFoundError")
    except {Entity}NotFoundError:
        pass  # Expected
    except Exception as e:
        all_validation_failures.append(f"Wrong exception: {e}")

    db.close()

    if all_validation_failures:
        print(f"VALIDATION FAILED - {len(all_validation_failures)}/{total_tests}:")
        for f in all_validation_failures:
            print(f"  - {f}")
        sys.exit(1)
    else:
        print(f"VALIDATION PASSED - All {total_tests} tests OK")
        sys.exit(0)

Checklist de Verificação

Antes de finalizar, verificar:

  • Lógica de negócio está no service (não em router/repository)
  • Validações de input (required, max length, format)
  • Repository injetado via DI no __init__
  • Chamadas LLM usam _tracer.start_as_current_span()
  • Prompts em métodos privados _build_prompt()
  • Bloco if __name__ == "__main__": com validação real
  • Exceções específicas do domínio (ex: {Entity}NotFoundError)
  • Docstrings em todos os métodos públicos
  • Type hints em parâmetros e retornos

使用示例

查看来源仓库中的使用示例与配置说明。

查看来源 ↗

来源历史

收录时间
2026-01-20
索引更新时间
2026-03-04
Branch
main

收录与同步日期属于本站记录。源码修改历史请查看来源仓库。

GitHub ↗

chat Comments (0)

chat_bubble_outline

No comments yet. Be the first to share your thoughts!