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}")

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.1.2.tar.gz (26.6 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.1.2-py3-none-any.whl (32.9 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for forgebase-0.1.2.tar.gz
Algorithm Hash digest
SHA256 3ca0acd83518287da7448e882661126e44fa0ada7faa5c8a88500b0a74bc460a
MD5 0cf571fa9392b15fb7014f6777ed0dfc
BLAKE2b-256 708252f494e44be85a246666e171657ddb5a49f2ec76ddb57eecfa3a7e72b51d

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for forgebase-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 4035841deade3caee8b4891b27588e5b375349e205f9e4cb59b9c239f6e62016
MD5 088212b90ae40d6bc1913c743046e248
BLAKE2b-256 f745e8af272505ef30ba83ee9631799ec06120de9cd129ca51de05b5e2454cff

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