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.LogServiceconfigura logging com console/arquivo rotativo e filtros.forge_utils.log_service.loggeré a instância global pronta para uso.forge_utils.pathsoferece 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 interfaceILLMClientcom 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(oupoetry run pytest -q). - Linters:
ruff check .emypy --config-file mypy.ini(compoetry runse estiver usando Poetry). - Build:
python -m buildgera 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3ca0acd83518287da7448e882661126e44fa0ada7faa5c8a88500b0a74bc460a
|
|
| MD5 |
0cf571fa9392b15fb7014f6777ed0dfc
|
|
| BLAKE2b-256 |
708252f494e44be85a246666e171657ddb5a49f2ec76ddb57eecfa3a7e72b51d
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4035841deade3caee8b4891b27588e5b375349e205f9e4cb59b9c239f6e62016
|
|
| MD5 |
088212b90ae40d6bc1913c743046e248
|
|
| BLAKE2b-256 |
f745e8af272505ef30ba83ee9631799ec06120de9cd129ca51de05b5e2454cff
|