本文へ移動
cccskills
無料GitHub で公開

llm-app-patterns

Padrões prontos para produção ao construir aplicações com LLM. Cobre pipelines RAG, arquiteturas de agentes, IDEs de prompt e monitoramento LLMOps. Use ao projetar aplicações com IA, implementar RAG, construir agentes ou configurar observabilidade de LLM.

インストール方法を見る

含まれるファイル(1)

  • SKILL.md21.9 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

🤖 Padrões de Aplicação LLM

Padrões prontos para produção ao construir aplicações com LLM, inspirados por Dify e melhores práticas da indústria.

Quando Usar Esta Skill

Use esta skill quando:

  • Projetar aplicações alimentadas por LLM
  • Implementar RAG (Retrieval-Augmented Generation)
  • Construir agentes de IA com ferramentas
  • Configurar monitoramento LLMOps
  • Escolher entre arquiteturas de agentes

1. Arquitetura de Pipeline RAG

Visão Geral

RAG (Retrieval-Augmented Generation) fundamenta respostas de LLM em seus dados.

┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│   Ingest    │────▶│   Retrieve  │────▶│   Generate  │
│  Documents  │     │   Context   │     │   Response  │
└─────────────┘     └─────────────┘     └─────────────┘
      │                   │                   │
      ▼                   ▼                   ▼
 ┌─────────┐       ┌───────────┐       ┌───────────┐
 │ Chunking│       │  Vector   │       │    LLM    │
 │Embedding│       │  Search   │       │  + Context│
 └─────────┘       └───────────┘       └───────────┘

1.1 Ingestão de Documentos

# Estratégias de chunking
class ChunkingStrategy:
    # Chunks de tamanho fixo (simples mas pode quebrar contexto)
    FIXED_SIZE = "fixed_size"  # ex: 512 tokens

    # Chunking semântico (preserva significado)
    SEMANTIC = "semantic"      # Divide em parágrafos/seções

    # Divisão recursiva (tenta múltiplos separadores)
    RECURSIVE = "recursive"    # ["\n\n", "\n", " ", ""]

    # Consciente de documento (respeita estrutura)
    DOCUMENT_AWARE = "document_aware"  # Cabeçalhos, listas, etc.

# Configurações recomendadas
CHUNK_CONFIG = {
    "chunk_size": 512,       # tokens
    "chunk_overlap": 50,     # sobreposição de tokens entre chunks
    "separators": ["\n\n", "\n", ". ", " "],
}

1.2 Embedding e Armazenamento

# Seleção de banco de dados vetorial
VECTOR_DB_OPTIONS = {
    "pinecone": {
        "use_case": "Produção, serviço gerenciado",
        "scale": "Bilhões de vetores",
        "features": ["Busca híbrida", "Filtragem de metadados"]
    },
    "weaviate": {
        "use_case": "Auto-hospedado, multi-modal",
        "scale": "Milhões de vetores",
        "features": ["API GraphQL", "Módulos"]
    },
    "chromadb": {
        "use_case": "Desenvolvimento, prototipagem",
        "scale": "Milhares de vetores",
        "features": ["API simples", "Opção em memória"]
    },
    "pgvector": {
        "use_case": "Infraestrutura Postgres existente",
        "scale": "Milhões de vetores",
        "features": ["Integração SQL", "Conformidade ACID"]
    }
}

# Seleção de modelo de embedding
EMBEDDING_MODELS = {
    "openai/text-embedding-3-small": {
        "dimensions": 1536,
        "cost": "$0.02/1M tokens",
        "quality": "Bom para a maioria dos casos de uso"
    },
    "openai/text-embedding-3-large": {
        "dimensions": 3072,
        "cost": "$0.13/1M tokens",
        "quality": "Melhor para queries complexas"
    },
    "local/bge-large": {
        "dimensions": 1024,
        "cost": "Gratuito (apenas computação)",
        "quality": "Comparável ao OpenAI small"
    }
}

1.3 Estratégias de Recuperação

# Busca semântica básica
def semantic_search(query: str, top_k: int = 5):
    query_embedding = embed(query)
    results = vector_db.similarity_search(
        query_embedding,
        top_k=top_k
    )
    return results

# Busca híbrida (semântica + palavra-chave)
def hybrid_search(query: str, top_k: int = 5, alpha: float = 0.5):
    """
    alpha=1.0: Semântica pura
    alpha=0.0: Palavra-chave pura (BM25)
    alpha=0.5: Balanceada
    """
    semantic_results = vector_db.similarity_search(query)
    keyword_results = bm25_search(query)

    # Reciprocal Rank Fusion
    return rrf_merge(semantic_results, keyword_results, alpha)

# Recuperação multi-query
def multi_query_retrieval(query: str):
    """Gera variações de query múltiplas para melhor recall"""
    queries = llm.generate_query_variations(query, n=3)
    all_results = []
    for q in queries:
        all_results.extend(semantic_search(q))
    return deduplicate(all_results)

# Compressão contextual
def compressed_retrieval(query: str):
    """Recupera e depois comprime apenas as partes relevantes"""
    docs = semantic_search(query, top_k=10)
    compressed = llm.extract_relevant_parts(docs, query)
    return compressed

1.4 Geração com Contexto

RAG_PROMPT_TEMPLATE = """
Responda a pergunta do usuário baseado APENAS no contexto a seguir.
Se o contexto não contiver informação suficiente, diga "Não tenho informação suficiente para responder isso."

Contexto:
{context}

Pergunta: {question}

Resposta:"""

def generate_with_rag(question: str):
    # Recuperar
    context_docs = hybrid_search(question, top_k=5)
    context = "\n\n".join([doc.content for doc in context_docs])

    # Gerar
    prompt = RAG_PROMPT_TEMPLATE.format(
        context=context,
        question=question
    )

    response = llm.generate(prompt)

    # Retornar com citações
    return {
        "answer": response,
        "sources": [doc.metadata for doc in context_docs]
    }

2. Arquiteturas de Agentes

2.1 Padrão ReAct (Raciocínio + Ação)

Pensamento: Preciso procurar por informação sobre X
Ação: search("X")
Observação: [resultados da busca]
Pensamento: Com base nos resultados, devo...
Ação: calculate(...)
Observação: [resultado do cálculo]
Pensamento: Agora tenho informação suficiente
Ação: final_answer("A resposta é...")
REACT_PROMPT = """
Você é um assistente de IA que pode usar ferramentas para responder perguntas.

Ferramentas disponíveis:
{tools_description}

Use este formato:
Pensamento: [seu raciocínio sobre o que fazer em seguida]
Ação: [tool_name(argumentos)]
Observação: [resultado da ferramenta - será preenchido]
... (repita Pensamento/Ação/Observação conforme necessário)
Pensamento: Tenho informação suficiente para responder
Resposta Final: [sua resposta final]

Pergunta: {question}
"""

class ReActAgent:
    def __init__(self, tools: list, llm):
        self.tools = {t.name: t for t in tools}
        self.llm = llm
        self.max_iterations = 10

    def run(self, question: str) -> str:
        prompt = REACT_PROMPT.format(
            tools_description=self._format_tools(),
            question=question
        )

        for _ in range(self.max_iterations):
            response = self.llm.generate(prompt)

            if "Resposta Final:" in response:
                return self._extract_final_answer(response)

            action = self._parse_action(response)
            observation = self._execute_tool(action)
            prompt += f"\nObservação: {observation}\n"

        return "Máximo de iterações atingido"

2.2 Padrão Function Calling

# Defina ferramentas como funções com schemas
TOOLS = [
    {
        "name": "search_web",
        "description": "Busca na web por informação atual",
        "parameters": {
            "type": "object",
            "properties": {
                "query": {
                    "type": "string",
                    "description": "Query de busca"
                }
            },
            "required": ["query"]
        }
    },
    {
        "name": "calculate",
        "description": "Realiza cálculos matemáticos",
        "parameters": {
            "type": "object",
            "properties": {
                "expression": {
                    "type": "string",
                    "description": "Expressão matemática a avaliar"
                }
            },
            "required": ["expression"]
        }
    }
]

class FunctionCallingAgent:
    def run(self, question: str) -> str:
        messages = [{"role": "user", "content": question}]

        while True:
            response = self.llm.chat(
                messages=messages,
                tools=TOOLS,
                tool_choice="auto"
            )

            if response.tool_calls:
                for tool_call in response.tool_calls:
                    result = self._execute_tool(
                        tool_call.name,
                        tool_call.arguments
                    )
                    messages.append({
                        "role": "tool",
                        "tool_call_id": tool_call.id,
                        "content": str(result)
                    })
            else:
                return response.content

2.3 Padrão Plan-and-Execute

class PlanAndExecuteAgent:
    """
    1. Criar um plano (lista de passos)
    2. Executar cada passo
    3. Replanejamento se necessário
    """

    def run(self, task: str) -> str:
        # Fase de planejamento
        plan = self.planner.create_plan(task)
        # Retorna: ["Passo 1: ...", "Passo 2: ...", ...]

        results = []
        for step in plan:
            # Executar cada passo
            result = self.executor.execute(step, context=results)
            results.append(result)

            # Verificar se replanejamento é necessário
            if self._needs_replan(task, results):
                new_plan = self.planner.replan(
                    task,
                    completed=results,
                    remaining=plan[len(results):]
                )
                plan = new_plan

        # Sintetizar resposta final
        return self.synthesizer.summarize(task, results)

2.4 Colaboração Multi-Agente

class AgentTeam:
    """
    Agentes especializados colaborando em tarefas complexas
    """

    def __init__(self):
        self.agents = {
            "researcher": ResearchAgent(),
            "analyst": AnalystAgent(),
            "writer": WriterAgent(),
            "critic": CriticAgent()
        }
        self.coordinator = CoordinatorAgent()

    def solve(self, task: str) -> str:
        # Coordenador atribui subtarefas
        assignments = self.coordinator.decompose(task)

        results = {}
        for assignment in assignments:
            agent = self.agents[assignment.agent]
            result = agent.execute(
                assignment.subtask,
                context=results
            )
            results[assignment.id] = result

        # Crítico revisa
        critique = self.agents["critic"].review(results)

        if critique.needs_revision:
            # Iterar com feedback
            return self.solve_with_feedback(task, results, critique)

        return self.coordinator.synthesize(results)

3. Padrões de Prompt IDE

3.1 Templates de Prompt com Variáveis

class PromptTemplate:
    def __init__(self, template: str, variables: list[str]):
        self.template = template
        self.variables = variables

    def format(self, **kwargs) -> str:
        # Validar todas as variáveis fornecidas
        missing = set(self.variables) - set(kwargs.keys())
        if missing:
            raise ValueError(f"Variáveis ausentes: {missing}")

        return self.template.format(**kwargs)

    def with_examples(self, examples: list[dict]) -> str:
        """Adicionar exemplos few-shot"""
        example_text = "\n\n".join([
            f"Entrada: {ex['input']}\nSaída: {ex['output']}"
            for ex in examples
        ])
        return f"{example_text}\n\n{self.template}"

# Uso
summarizer = PromptTemplate(
    template="Resuma o seguinte texto em estilo {style}:\n\n{text}",
    variables=["style", "text"]
)

prompt = summarizer.format(
    style="profissional",
    text="Conteúdo de artigo longo..."
)

3.2 Versionamento de Prompt e Testes A/B

class PromptRegistry:
    def __init__(self, db):
        self.db = db

    def register(self, name: str, template: str, version: str):
        """Armazenar prompt com versão"""
        self.db.save({
            "name": name,
            "template": template,
            "version": version,
            "created_at": datetime.now(),
            "metrics": {}
        })

    def get(self, name: str, version: str = "latest") -> str:
        """Recuperar versão específica"""
        return self.db.get(name, version)

    def ab_test(self, name: str, user_id: str) -> str:
        """Retornar variante baseada em bucket do usuário"""
        variants = self.db.get_all_versions(name)
        bucket = hash(user_id) % len(variants)
        return variants[bucket]

    def record_outcome(self, prompt_id: str, outcome: dict):
        """Rastrear desempenho do prompt"""
        self.db.update_metrics(prompt_id, outcome)

3.3 Prompt Chaining

class PromptChain:
    """
    Encadeia prompts, passando saída como entrada para o próximo
    """

    def __init__(self, steps: list[dict]):
        self.steps = steps

    def run(self, initial_input: str) -> dict:
        context = {"input": initial_input}
        results = []

        for step in self.steps:
            prompt = step["prompt"].format(**context)
            output = llm.generate(prompt)

            # Analisar saída se necessário
            if step.get("parser"):
                output = step["parser"](output)

            context[step["output_key"]] = output
            results.append({
                "step": step["name"],
                "output": output
            })

        return {
            "final_output": context[self.steps[-1]["output_key"]],
            "intermediate_results": results
        }

# Exemplo: Pesquisar → Analisar → Resumir
chain = PromptChain([
    {
        "name": "research",
        "prompt": "Pesquise sobre o tópico: {input}",
        "output_key": "research"
    },
    {
        "name": "analyze",
        "prompt": "Analise esses achados:\n{research}",
        "output_key": "analysis"
    },
    {
        "name": "summarize",
        "prompt": "Resuma essa análise em 3 pontos principais:\n{analysis}",
        "output_key": "summary"
    }
])

4. LLMOps e Observabilidade

4.1 Métricas para Rastrear

LLM_METRICS = {
    # Performance
    "latency_p50": "Tempo de resposta percentil 50",
    "latency_p99": "Tempo de resposta percentil 99",
    "tokens_per_second": "Velocidade de geração",

    # Qualidade
    "user_satisfaction": "Taxa de polegar para cima/baixo",
    "task_completion": "% de tarefas completadas com sucesso",
    "hallucination_rate": "% de respostas com erros factuais",

    # Custo
    "cost_per_request": "Média R$ por chamada de API",
    "tokens_per_request": "Média de tokens usados",
    "cache_hit_rate": "% de requisições servidas do cache",

    # Confiabilidade
    "error_rate": "% de requisições falhadas",
    "timeout_rate": "% de requisições que expiraram",
    "retry_rate": "% de requisições precisando retry"
}

4.2 Logging e Rastreamento

import logging
from opentelemetry import trace

tracer = trace.get_tracer(__name__)

class LLMLogger:
    def log_request(self, request_id: str, data: dict):
        """Log de requisição LLM para debug e análise"""
        log_entry = {
            "request_id": request_id,
            "timestamp": datetime.now().isoformat(),
            "model": data["model"],
            "prompt": data["prompt"][:500],  # Truncar para armazenamento
            "prompt_tokens": data["prompt_tokens"],
            "temperature": data.get("temperature", 1.0),
            "user_id": data.get("user_id"),
        }
        logging.info(f"LLM_REQUEST: {json.dumps(log_entry)}")

    def log_response(self, request_id: str, data: dict):
        """Log de resposta LLM"""
        log_entry = {
            "request_id": request_id,
            "completion_tokens": data["completion_tokens"],
            "total_tokens": data["total_tokens"],
            "latency_ms": data["latency_ms"],
            "finish_reason": data["finish_reason"],
            "cost_usd": self._calculate_cost(data),
        }
        logging.info(f"LLM_RESPONSE: {json.dumps(log_entry)}")

# Rastreamento distribuído
@tracer.start_as_current_span("llm_call")
def call_llm(prompt: str) -> str:
    span = trace.get_current_span()
    span.set_attribute("prompt.length", len(prompt))

    response = llm.generate(prompt)

    span.set_attribute("response.length", len(response))
    span.set_attribute("tokens.total", response.usage.total_tokens)

    return response.content

4.3 Framework de Avaliação

class LLMEvaluator:
    """
    Avalia saídas de LLM para qualidade
    """

    def evaluate_response(self,
                          question: str,
                          response: str,
                          ground_truth: str = None) -> dict:
        scores = {}

        # Relevância: Ela responde à pergunta?
        scores["relevance"] = self._score_relevance(question, response)

        # Coerência: Está bem estruturada?
        scores["coherence"] = self._score_coherence(response)

        # Fundamentação: Está baseada em contexto fornecido?
        scores["groundedness"] = self._score_groundedness(response)

        # Precisão: Coincide com a verdade comprovada?
        if ground_truth:
            scores["accuracy"] = self._score_accuracy(response, ground_truth)

        # Segurança: Está segura?
        scores["safety"] = self._score_safety(response)

        return scores

    def run_benchmark(self, test_cases: list[dict]) -> dict:
        """Executar avaliação em conjunto de testes"""
        results = []
        for case in test_cases:
            response = llm.generate(case["prompt"])
            scores = self.evaluate_response(
                question=case["prompt"],
                response=response,
                ground_truth=case.get("expected")
            )
            results.append(scores)

        return self._aggregate_scores(results)

5. Padrões de Produção

5.1 Estratégia de Cache

import hashlib
from functools import lru_cache

class LLMCache:
    def __init__(self, redis_client, ttl_seconds=3600):
        self.redis = redis_client
        self.ttl = ttl_seconds

    def _cache_key(self, prompt: str, model: str, **kwargs) -> str:
        """Gerar chave de cache determinística"""
        content = f"{model}:{prompt}:{json.dumps(kwargs, sort_keys=True)}"
        return hashlib.sha256(content.encode()).hexdigest()

    def get_or_generate(self, prompt: str, model: str, **kwargs) -> str:
        key = self._cache_key(prompt, model, **kwargs)

        # Verificar cache
        cached = self.redis.get(key)
        if cached:
            return cached.decode()

        # Gerar
        response = llm.generate(prompt, model=model, **kwargs)

        # Cache (apenas cache saídas determinísticas)
        if kwargs.get("temperature", 1.0) == 0:
            self.redis.setex(key, self.ttl, response)

        return response

5.2 Rate Limiting e Retry

import time
from tenacity import retry, wait_exponential, stop_after_attempt

class RateLimiter:
    def __init__(self, requests_per_minute: int):
        self.rpm = requests_per_minute
        self.timestamps = []

    def acquire(self):
        """Aguardar se limite de taxa fosse excedido"""
        now = time.time()

        # Remover timestamps antigos
        self.timestamps = [t for t in self.timestamps if now - t < 60]

        if len(self.timestamps) >= self.rpm:
            sleep_time = 60 - (now - self.timestamps[0])
            time.sleep(sleep_time)

        self.timestamps.append(time.time())

# Retry com backoff exponencial
@retry(
    wait=wait_exponential(multiplier=1, min=4, max=60),
    stop=stop_after_attempt(5)
)
def call_llm_with_retry(prompt: str) -> str:
    try:
        return llm.generate(prompt)
    except RateLimitError:
        raise  # Acionará retry
    except APIError as e:
        if e.status_code >= 500:
            raise  # Retry erros de servidor
        raise  # Não retry erros de cliente

5.3 Estratégia de Fallback

class LLMWithFallback:
    def __init__(self, primary: str, fallbacks: list[str]):
        self.primary = primary
        self.fallbacks = fallbacks

    def generate(self, prompt: str, **kwargs) -> str:
        models = [self.primary] + self.fallbacks

        for model in models:
            try:
                return llm.generate(prompt, model=model, **kwargs)
            except (RateLimitError, APIError) as e:
                logging.warning(f"Modelo {model} falhou: {e}")
                continue

        raise AllModelsFailedError("Todos os modelos esgotados")

# Uso
llm_client = LLMWithFallback(
    primary="gpt-4-turbo",
    fallbacks=["gpt-3.5-turbo", "claude-3-sonnet"]
)

Matriz de Decisão Arquitetônica

PadrãoUse QuandoComplexidadeCusto
RAG SimplesFAQ, busca docsBaixaBaixo
RAG HíbridoQueries mistasMédiaMédio
Agente ReActTarefas multi-etapaMédiaMédio
Function CallingFerramentas estruturadasBaixaBaixo
Plan-ExecuteTarefas complexasAltaAlta
Multi-AgenteTarefas de pesquisaMuito AltaMuito Alta

Recursos

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Especialista em construir experiências 3D para a web - Three.js, React Three Fiber, Spline, WebGL e cenas 3D interativas. Cobre configuradores de produtos, portfólios 3D, websites imersivos e adição de profundidade às experiências web. Use quando: website 3D, three.js, WebGL, react three fiber, experiência 3D.

日本語の概要は準備中です。原文の説明を表示しています。

artubss/SKILLS-CLAUDE-CODE112026年5月17日 更新

Quando o usuário quer planejar, projetar ou implementar um teste A/B ou experimento. Também use quando o usuário menciona "teste A/B", "split test", "experimento", "testar essa mudança", "copy variante", "teste multivariado" ou "hipótese". Para implementação de rastreamento, veja analytics-tracking.

日本語の概要は準備中です。原文の説明を表示しています。

artubss/SKILLS-CLAUDE-CODE112026年5月17日 更新

Auditar e melhorar a acessibilidade web seguindo as diretrizes WCAG 2.1. Use quando solicitado para "melhorar acessibilidade", "auditoria a11y", "conformidade WCAG", "suporte a leitor de tela", "navegação por teclado" ou "tornar acessível".

日本語の概要は準備中です。原文の説明を表示しています。

artubss/SKILLS-CLAUDE-CODE112026年5月17日 更新

Testes e benchmarking de agentes LLM incluindo testes comportamentais, avaliação de capacidades, métricas de confiabilidade e monitoramento em produção—onde até os melhores agentes alcançam menos de 50% em benchmarks do mundo real. Use quando: testes de agentes, avaliação de agentes, benchmark de agentes, confiabilidade de agentes, teste de agentes.

日本語の概要は準備中です。原文の説明を表示しています。

artubss/SKILLS-CLAUDE-CODE112026年5月17日 更新

Criar, gerenciar e orquestrar agentes de IA usando o CLI AI Maestro. Use quando o usuário pedir para "criar agente", "listar agentes", "deletar agente", "hibernar agente", "despertar agente", "instalar plugin", "mostrar agente", "reiniciar agente" ou qualquer tarefa de gerenciamento do ciclo de vida do agente.

日本語の概要は準備中です。原文の説明を表示しています。

artubss/SKILLS-CLAUDE-CODE112026年5月17日 更新

Gerencie múltiplos agentes CLI locais via sessões tmux (iniciar/parar/monitorar/atribuir) com agendamento compatível com cron.

日本語の概要は準備中です。原文の説明を表示しています。

artubss/SKILLS-CLAUDE-CODE112026年5月17日 更新

artubss のスキルをすべて見る

このスキルの問題を報告する