Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
| title: ML Intern | |
| emoji: π€ | |
| colorFrom: yellow | |
| colorTo: blue | |
| sdk: docker | |
| app_port: 7860 | |
| hf_oauth: true | |
| hf_oauth_expiration_minutes: 43200 | |
| hf_oauth_scopes: | |
| - read-repos | |
| - write-repos | |
| - contribute-repos | |
| - manage-repos | |
| - inference-api | |
| - jobs | |
| - write-discussions | |
| <p align="center"> | |
| <img src="frontend/public/smolagents.webp" alt="smolagents logo" width="160" /> | |
| </p> | |
| # ML Intern | |
| An ML intern that autonomously researches, writes, and ships good quality ML related code using the Hugging Face ecosystem β with deep access to docs, papers, datasets, and cloud compute. | |
| ## Quick Start | |
| ### Installation | |
| ```bash | |
| git clone git@github.com:huggingface/ml-intern.git | |
| cd ml-intern | |
| uv sync | |
| uv tool install -e . | |
| ``` | |
| #### That's it. Now `ml-intern` works from any directory: | |
| ```bash | |
| ml-intern | |
| ``` | |
| Create a `.env` file in the project root (or export these in your shell): | |
| ```bash | |
| ANTHROPIC_API_KEY=<your-anthropic-api-key> # if using anthropic models | |
| OPENAI_API_KEY=<your-openai-api-key> # if using openai models | |
| HF_TOKEN=<your-hugging-face-token> | |
| GITHUB_TOKEN=<github-personal-access-token> | |
| ``` | |
| If no `HF_TOKEN` is set, the CLI will prompt you to paste one on first launch. To get a GITHUB_TOKEN follow the tutorial [here](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-fine-grained-personal-access-token). | |
| ### Usage | |
| **Interactive mode** (start a chat session): | |
| ```bash | |
| ml-intern | |
| ``` | |
| **Headless mode** (single prompt, auto-approve): | |
| ```bash | |
| ml-intern "fine-tune llama on my dataset" | |
| ``` | |
| **Options:** | |
| ```bash | |
| ml-intern --model anthropic/claude-opus-4-6 "your prompt" | |
| ml-intern --model openai/gpt-5.5 "your prompt" | |
| ml-intern --max-iterations 100 "your prompt" | |
| ml-intern --no-stream "your prompt" | |
| ``` | |
| ## Architecture | |
| ### Component Overview | |
| ``` | |
| βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| β User/CLI β | |
| ββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββ¬βββββββββββ | |
| β Operations β Events | |
| β (user_input, exec_approval, β | |
| submission_queue interrupt, compact, ...) event_queue | |
| β β | |
| β β | |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββ β | |
| β submission_loop (agent_loop.py) β β | |
| β ββββββββββββββββββββββββββββββββββββββββββββββββ β β | |
| β β 1. Receive Operation from queue β β β | |
| β β 2. Route to handler (run_agent/compact/...) β β β | |
| β ββββββββββββββββββββββββββββββββββββββββββββββββ β β | |
| β β β β | |
| β ββββββββββββββββββββββββββββββββββββββββββββββββ β β | |
| β β Handlers.run_agent() β ββββ€ | |
| β β β β β | |
| β β ββββββββββββββββββββββββββββββββββββββββββ β β β | |
| β β β Agentic Loop (max 300 iterations) β β β β | |
| β β β β β β β | |
| β β β ββββββββββββββββββββββββββββββββββββ β β β β | |
| β β β β Session β β β β β | |
| β β β β ββββββββββββββββββββββββββββββ β β β β β | |
| β β β β β ContextManager β β β β β β | |
| β β β β β β’ Message history β β β β β β | |
| β β β β β (litellm.Message[]) β β β β β β | |
| β β β β β β’ Auto-compaction (170k) β β β β β β | |
| β β β β β β’ Session upload to HF β β β β β β | |
| β β β β ββββββββββββββββββββββββββββββ β β β β β | |
| β β β β β β β β β | |
| β β β β ββββββββββββββββββββββββββββββ β β β β β | |
| β β β β β ToolRouter β β β β β β | |
| β β β β β ββ HF docs & research β β β β β β | |
| β β β β β ββ HF repos, datasets, β β β β β β | |
| β β β β β β jobs, papers β β β β β β | |
| β β β β β ββ GitHub code search β β β β β β | |
| β β β β β ββ Sandbox & local tools β β β β β β | |
| β β β β β ββ Planning β β β β β β | |
| β β β β β ββ MCP server tools β β β β β β | |
| β β β β ββββββββββββββββββββββββββββββ β β β β β | |
| β β β ββββββββββββββββββββββββββββββββββββ β β β β | |
| β β β β β β β | |
| β β β ββββββββββββββββββββββββββββββββββββ β β β β | |
| β β β β Doom Loop Detector β β β β β | |
| β β β β β’ Detects repeated tool patterns β β β β β | |
| β β β β β’ Injects corrective prompts β β β β β | |
| β β β ββββββββββββββββββββββββββββββββββββ β β β β | |
| β β β β β β β | |
| β β β Loop: β β β β | |
| β β β 1. LLM call (litellm.acompletion) β β β β | |
| β β β β β β β β | |
| β β β 2. Parse tool_calls[] β β β β | |
| β β β β β β β β | |
| β β β 3. Approval check β β β β | |
| β β β (jobs, sandbox, destructive ops) β β β β | |
| β β β β β β β β | |
| β β β 4. Execute via ToolRouter β β β β | |
| β β β β β β β β | |
| β β β 5. Add results to ContextManager β β β β | |
| β β β β β β β β | |
| β β β 6. Repeat if tool_calls exist β β β β | |
| β β ββββββββββββββββββββββββββββββββββββββββββ β β β | |
| β ββββββββββββββββββββββββββββββββββββββββββββββββ β β | |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββ΄βββ | |
| ``` | |
| ### Agentic Loop Flow | |
| ``` | |
| User Message | |
| β | |
| [Add to ContextManager] | |
| β | |
| βββββββββββββββββββββββββββββββββββββββββββββ | |
| β Iteration Loop (max 300) β | |
| β β | |
| β Get messages + tool specs β | |
| β β β | |
| β litellm.acompletion() β | |
| β β β | |
| β Has tool_calls? ββNoββ> Done β | |
| β β β | |
| β Yes β | |
| β β β | |
| β Add assistant msg (with tool_calls) β | |
| β β β | |
| β Doom loop check β | |
| β β β | |
| β For each tool_call: β | |
| β β’ Needs approval? ββYesββ> Wait for β | |
| β β user confirm β | |
| β No β | |
| β β β | |
| β β’ ToolRouter.execute_tool() β | |
| β β’ Add result to ContextManager β | |
| β β β | |
| β Continue loop ββββββββββββββββββ β | |
| β β β β | |
| β βββββββββββββββββββββββββ β | |
| βββββββββββββββββββββββββββββββββββββββββββββ | |
| ``` | |
| ## Events | |
| The agent emits the following events via `event_queue`: | |
| - `processing` - Starting to process user input | |
| - `ready` - Agent is ready for input | |
| - `assistant_chunk` - Streaming token chunk | |
| - `assistant_message` - Complete LLM response text | |
| - `assistant_stream_end` - Token stream finished | |
| - `tool_call` - Tool being called with arguments | |
| - `tool_output` - Tool execution result | |
| - `tool_log` - Informational tool log message | |
| - `tool_state_change` - Tool execution state transition | |
| - `approval_required` - Requesting user approval for sensitive operations | |
| - `turn_complete` - Agent finished processing | |
| - `error` - Error occurred during processing | |
| - `interrupted` - Agent was interrupted | |
| - `compacted` - Context was compacted | |
| - `undo_complete` - Undo operation completed | |
| - `shutdown` - Agent shutting down | |
| ## Development | |
| ### Adding Built-in Tools | |
| Edit `agent/core/tools.py`: | |
| ```python | |
| def create_builtin_tools() -> list[ToolSpec]: | |
| return [ | |
| ToolSpec( | |
| name="your_tool", | |
| description="What your tool does", | |
| parameters={ | |
| "type": "object", | |
| "properties": { | |
| "param": {"type": "string", "description": "Parameter description"} | |
| }, | |
| "required": ["param"] | |
| }, | |
| handler=your_async_handler | |
| ), | |
| # ... existing tools | |
| ] | |
| ``` | |
| ### Adding MCP Servers | |
| Edit `configs/cli_agent_config.json` for CLI defaults, or | |
| `configs/frontend_agent_config.json` for web-session defaults: | |
| ```json | |
| { | |
| "model_name": "anthropic/claude-sonnet-4-5-20250929", | |
| "mcpServers": { | |
| "your-server-name": { | |
| "transport": "http", | |
| "url": "https://example.com/mcp", | |
| "headers": { | |
| "Authorization": "Bearer ${YOUR_TOKEN}" | |
| } | |
| } | |
| } | |
| } | |
| ``` | |
| Note: Environment variables like `${YOUR_TOKEN}` are auto-substituted from `.env`. | |