Skip to main content

Forgebase core libraries (utils, framework e cliente LLM)

Project description

Forgebase

Forgebase reúne três blocos principais usados neste monorepo:

  • forge_utils – logging estruturado e utilidades de paths/configuração.
  • forgebase – framework MVC-C enxuto baseado em Pydantic v2 (modelos, commands, controllers, views e persistência).
  • llm_client – cliente agnóstico para a OpenAI Responses API com suporte a streaming, tool calling e replays offline.

A biblioteca está disponível em PyPI e também no TestPyPI para validação prévia.

Instalação rápida

pip install forgebase

Crie um ambiente virtual limpo antes de instalar (python -m venv .venv && source .venv/bin/activate).

Pacote por pacote

forge_utils

  • forge_utils.log_service.LogService configura logging com console/arquivo rotativo e filtros.
  • forge_utils.log_service.logger é a instância global pronta para uso.
  • forge_utils.paths oferece helpers (build_app_paths, ensure_dirs) para organizar arquivos de configuração, histórico e cache.

forgebase

Reexporta o framework MVC-C básico. Os pontos de entrada mais usados são:

  • CustomBaseModel / BaseModelData: modelos Pydantic com suporte a dirty tracking e observers.
  • CustomCommandBase + guard_errors: encapsulam regras de negócio, padronizando o tratamento de exceções (CommandException).
  • CustomBaseController / CustomBaseView: composição MVC-C mínima.
  • PersistenceFactory + JsonPersistence: persistência compatível com Pydantic v2.

Todos estes nomes estão disponíveis diretamente com from forgebase import ....

llm_client

O cliente LLM também é reexportado por forgebase para facilitar o consumo:

  • LLMOpenAIClient: wrapper para chamadas síncronas e streaming na OpenAI Responses API.
  • OpenAIProvider: implementação da interface ILLMClient com orquestração de tool calling.
  • Tool: modelo Pydantic que representa o schema JSON das ferramentas.
  • APIResponseError / ConfigurationError: exceções específicas do cliente.
  • ContentPart, OutputMessage, ResponseResult, TextFormat, TextOutputConfig: modelos retornados pelo Responses API.
  • Pronto para múltiplos LLMs: hoje o pacote vem com o provider OpenAI, mas a camada (ILLMClient) e os hooks de eventos foram pensados para suportar conectores adicionais (ex.: Llama, OpenRouter) sem alterar o código que consome o cliente.

Guia rápido de uso

Core MVC-C

from forgebase import CustomBaseModel, CustomCommandBase, JsonPersistence, guard_errors

class User(CustomBaseModel):
    id: int
    name: str

class CreateUserCommand(CustomCommandBase):
    @guard_errors
    def execute(self, payload: dict) -> User:
        model = User(**payload)
        # ... lógica de negócio ...
        return model

storage = JsonPersistence("users.json")

Cliente LLM – configuração e chamadas

Crie um arquivo .env na raiz do projeto (ou exporte no shell) com:

OPENAI_API_KEY=sk-...

Todos os exemplos abaixo carregam essa chave automaticamente via python-dotenv.

Chamada síncrona

import os
from dotenv import load_dotenv
from forgebase import APIResponseError, ConfigurationError, LLMOpenAIClient

load_dotenv()
client = LLMOpenAIClient(api_key=os.environ["OPENAI_API_KEY"], model="gpt-4o-mini")

try:
    response = client.send_prompt("Por que o céu é azul?")
    answer = "\n".join(
        part.text.strip()
        for item in response.output
        for part in getattr(item, "content", [item])
        if getattr(part, "text", None)
    )
    print(answer)
except (APIResponseError, ConfigurationError) as exc:
    print(f"Falha na chamada: {exc}")

Configurando timeout (⭐ novo na v0.2.0)

Por padrão, as chamadas HTTP usam timeout de 120 segundos. Você pode customizar:

# Timeout de 45 segundos
client = LLMOpenAIClient(
    api_key=os.environ["OPENAI_API_KEY"],
    timeout=45  # segundos
)

# Ou via OpenAIProvider
from forgebase import OpenAIProvider

provider = OpenAIProvider(timeout=45)
provider.set_api_key(os.environ["OPENAI_API_KEY"])
result = provider.send_message("Hello")

Importante: O timeout se aplica ao tempo total incluindo retries. Com timeout=45 e max_tries=4, o sistema não ultrapassará 45 segundos mesmo com múltiplas tentativas.

Chamada com streaming

import os
from dotenv import load_dotenv
from forgebase import LLMOpenAIClient

load_dotenv()
client = LLMOpenAIClient(api_key=os.environ["OPENAI_API_KEY"], model="gpt-4o-mini")

stream = client.send_prompt("Conte uma história curta sobre um robô e uma criança.", streamed=True)
for delta in stream:
    print(delta, end="", flush=True)
print()

Chamada multimodal (imagem + áudio)

import os
from dotenv import load_dotenv
from forgebase import LLMOpenAIClient

load_dotenv()
client = LLMOpenAIClient(api_key=os.environ["OPENAI_API_KEY"], model="gpt-4o")

response = client.send_prompt(
    "Descreva a imagem e comente o áudio anexado.",
    images=["https://upload.wikimedia.org/wikipedia/commons/9/99/Colorful_sunset.jpg"],
    audio={"base64": "ZGF0YQ==", "mime_type": "audio/wav"},
)
print(response)

Listar modelos disponíveis

import os
from dotenv import load_dotenv
from forgebase import LLMOpenAIClient

load_dotenv()
client = LLMOpenAIClient(api_key=os.environ["OPENAI_API_KEY"])
models = client.list_models()
print(models["data"][0])

Tool calling síncrono

import os
from dotenv import load_dotenv
from forgebase import OpenAIProvider, Tool

load_dotenv()
provider = OpenAIProvider()
provider.set_api_key(os.environ["OPENAI_API_KEY"])

tool = Tool(
    type="function",
    name="say_hello",
    parameters={"type": "object", "properties": {"who": {"type": "string"}}, "required": ["who"]},
)
provider.configure_tools([tool], tool_choice="required")
provider.register_tool("say_hello", lambda args: f"Olá, {args['who']}!")

print(provider.send_message("Cumprimente Forgebase."))

Tool calling com streaming

import os
from dotenv import load_dotenv
from forgebase import OpenAIProvider, Tool

load_dotenv()
provider = OpenAIProvider()
provider.set_api_key(os.environ["OPENAI_API_KEY"])

tool = Tool(
    type="function",
    name="summarize_numbers",
    parameters={"type": "object", "properties": {"nums": {"type": "array", "items": {"type": "number"}}}},
)
provider.configure_tools([tool], tool_choice="auto")
provider.register_tool("summarize_numbers", lambda args: sum(args.get("nums", [])))

for chunk in provider.send_stream("Considere os números 2, 4, 6 e mostre a soma."):
    print(chunk, end="", flush=True)
print()

Hooks de eventos

Tanto o LLMOpenAIClient quanto o OpenAIProvider expõem um sistema simples de hooks para instrumentar o fluxo:

from forgebase import LLMOpenAIClient, OpenAIProvider

client = LLMOpenAIClient(api_key=os.environ["OPENAI_API_KEY"])
client.register_hook("before_request", lambda ctx: print("▶", ctx["prompt"]))
client.register_hook("after_response", lambda ctx: print("◀", ctx.get("response")))

provider = OpenAIProvider(client=client)
provider.register_hook("before_tool_call", lambda ctx: print("tool", ctx["tool"]))
provider.register_hook("after_tool_call", lambda ctx: print("tool result", ctx["result"]))

Eventos disponíveis:

  • before_request, after_response, on_error, on_cache_hit (cliente LLM)
  • before_send, after_send, on_error, before_tool_call, after_tool_call, tool_error, cache_hit (provider)

Demo completo

O projeto inclui uma demo mais abrangente que cobre respostas diretas, streaming, (tool calling) e replays offline:

PYTHONPATH=shared/src:apps/llm_client/src python -m llm_client.example_full_usage

No Windows (PowerShell):

$env:PYTHONPATH = "shared/src;apps/llm_client/src"
python -m llm_client.example_full_usage

O arquivo apps/llm_client/src/llm_client/example_full_usage.py comenta cada etapa (passos para configurar OPENAI_API_KEY, habilitar tool calling real com DEMO_TOOL_CALLING=1, e como funciona o replay offline).

Configuração do ambiente

Opção 1 – Poetry (recomendada)

O pyproject.toml já descreve todos os pacotes via path. Basta executar na raiz:

poetry install
poetry run pytest -q
poetry run python -m llm_client.example_full_usage

O Poetry cria e gerencia o ambiente virtual automaticamente; não é necessário ajustar o PYTHONPATH manualmente.

Opção 2 – pip + requirements

Se preferir pip, gere um virtualenv e instale as dependências de desenvolvimento com o arquivo requirements-dev.txt gerado a partir do pyproject:

python -m venv .venv
source .venv/bin/activate
python -m pip install -U pip
python -m pip install -r requirements-dev.txt

O arquivo pode ser sincronizado com o pyproject.toml executando python requirements-dev.py. Depois disso, exporte PYTHONPATH=shared/src:framework/src:apps/llm_client/src:cli/src (ou use python -m para os módulos) e rode pytest -q normalmente.

Desenvolvimento local

  • Testes: pytest -q (ou poetry run pytest -q).
  • Linters: ruff check . e mypy --config-file mypy.ini (com poetry run se estiver usando Poetry).
  • Build: python -m build gera wheel/sdist para publicar em TestPyPI/PyPI.

Onde continuar

  • docs/api/openai_responses.md: detalhes da Responses API e eventos de streaming.
  • docs/api/openai_responses_tool_calling.md: guia de tool calling, payloads e replays.
  • docs/architecture/forgebase-architecture.md: visão completa da arquitetura e fluxos.
  • docs/release-guide.md: processo recomendado de versionamento e publicação.
  • docs/testing-strategy.md: abordagem de testes e boas práticas.
  • docs/configuration.md: variáveis de ambiente e diretórios importantes.
  • docs/providers/adding-new-provider.md: instruções para suportar novos LLMs.
  • docs/cli/usage.md: comandos expostos pela CLI.
  • docs/CONTRIBUTING.md: convenções de contribuição.
  • docs/adr/README.md: decisões arquiteturais registradas.
  • docs/tech-debts/TD-001-Robustez-Tool-Calling-Responses.md: backlog de melhorias planejadas.

Sinta-se à vontade para abrir issues ou PRs com sugestões e correções.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

forgebase-0.2.0.tar.gz (29.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

forgebase-0.2.0-py3-none-any.whl (35.3 kB view details)

Uploaded Python 3

File details

Details for the file forgebase-0.2.0.tar.gz.

File metadata

  • Download URL: forgebase-0.2.0.tar.gz
  • Upload date:
  • Size: 29.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.2 CPython/3.12.3 Linux/6.6.87.2-microsoft-standard-WSL2

File hashes

Hashes for forgebase-0.2.0.tar.gz
Algorithm Hash digest
SHA256 dbff882bc453f3945f3ca48f4622d9220876b5c014e2c882dfd6e2c42b0702e3
MD5 dec9b56ae9c8b2a55b39e27146a54e1f
BLAKE2b-256 4908c86afc5b267221962747d5800382c0a43d97940561d1d07a8fdcd797f9d5

See more details on using hashes here.

File details

Details for the file forgebase-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: forgebase-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 35.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.2 CPython/3.12.3 Linux/6.6.87.2-microsoft-standard-WSL2

File hashes

Hashes for forgebase-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6a8e34cb871ca4172355ae8a55a762b65c58fc59945be94f04505070781bc51a
MD5 609aacb3795765e915436606d11d37e9
BLAKE2b-256 03a8e94d10dd3cb41ca947d328867de994c78bec56caee57cc70cd7868e09b85

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page