Skip to content

Migration Guide

From MALMAS to Feature Forge

Configuration

Before (MALMAS):

import global_config
# Mutable global state
global_config.task = "classification"
global_config.metric = "auc"

After (Feature Forge):

from feature_forge.config import Settings

# Immutable, validated, instance-based
settings = Settings(task="classification", metric="auc")
# Or via env var: FF_TASK=classification

Secrets Management: - Non-sensitive defaults are now in config/settings.yaml - Only secrets (API keys) go in .env (encrypted with dotenvx) - Use FF_LLM__API_KEY for a single key across all providers, or set provider-specific keys (DEEPSEEK_API_KEY, OPENAI_API_KEY, etc.)

LLM Client

Before:

from main_demo.main_func import generate_response
response = generate_response(model, api_key, base_url, prompt, user_msg, temp)

After:

from feature_forge.llm import LangfuseLLMWrapper, DiskCache
from feature_forge.llm.providers import DeepSeekProvider

client = LangfuseLLMWrapper(
    DeepSeekProvider(api_key="sk-..."),
    cache=DiskCache(),
)
response = await client.complete(messages=[...])

Agents

Before:

# Agents were functions with hardcoded prompt paths
# No registry, no plugin system

After:

from feature_forge.agents import AgentRegistry, UnaryFeatureAgent

# Discover all agents
agents = AgentRegistry.get_builtin_agents()
agent = agents["unary"](config, llm_client)

Memory

Before:

from main_demo.memory import AgentMemory
memory = AgentMemory("unary", "project", "cache_dir", 0)

After:

from feature_forge.memory import AgentMemory
memory = AgentMemory("unary", "memory_files/unary_memory.json")

Pipeline

Before:

# Monolithic pipeline in notebooks

After:

from feature_forge.api import MALMASFeatureEngineer

fe = MALMASFeatureEngineer()
fe.fit(X_train, y_train)
X_test_enhanced = fe.transform(X_test)

Experiment Tracking

Before:

# No built-in tracking

After:

from feature_forge.experiment import ExperimentRunner, WandBTracker

tracker = WandBTracker(project="feature-forge")
runner = ExperimentRunner(tracker=tracker)

Breaking Changes

  1. Global config removed → Use Settings() instances
  2. Agent names changed → Use AgentRegistry for discovery
  3. Memory path format → Now uses single JSON file per agent
  4. LLM interface → Now async with LLMClient.complete()
  5. Metrics → Now in feature_forge.evaluation.metrics
  6. API Key Configuration → Use FF_LLM__API_KEY for all providers, or set provider-specific keys directly. Keys are passed to LLM clients via config, not auto-propagated to environment variables.