# LLMGenerateStep Component Usage

## Importing

```python
from recipe_executor.steps.llm_generate import LLMGenerateStep, LLMGenerateConfig
```

## Configuration

The LLMGenerateStep is configured with a LLMGenerateConfig:

```python
class LLMGenerateConfig(StepConfig):
    """
    Config for LLMGenerateStep.

    Fields:
        prompt: The prompt to send to the LLM (templated beforehand).
        model: The model identifier to use (provider/model_name format).
        max_tokens: The maximum number of tokens for the LLM response.
        mcp_servers: List of MCP servers for access to tools.
        output_format: The format of the LLM output (text, files, or JSON).
            - text: Plain text output.
            - files: List of files generated by the LLM.
            - object: Object based on the provided JSON schema.
            - list: List of items based on the provided JSON schema.
        output_key: The name under which to store the LLM output in context.
    """

    prompt: str
    model: str = "openai/gpt-4o"
    max_tokens: Optional[Union[str, int]] = None
    mcp_servers: Optional[List[Dict[str, Any]]] = None
    output_format: "text" | "files" | Dict[str, Any]
    output_key: str = "llm_output"
```

## Basic Usage in Recipes

The LLMGenerateStep can be used in recipes via the `llm_generate` step type:

```json
{
  "steps": [
    {
      "type": "llm_generate",
      "config": {
        "prompt": "What is the weather in Redmond, WA today?",
        "model": "openai/o4-mini",
        "mcp_servers": [
          {
            "url": "http://localhost:3001/sse"
          }
        ],
        "output_format": "text",
        "output_key": "capital_result"
      }
    }
  ]
}
```

## Template-Based Prompts

The prompt can include template variables from the context:

```json
{
  "steps": [
    {
      "type": "read_files",
      "config": {
        "path": "specs/component_spec.md",
        "content_key": "component_spec_content"
      }
    },
    {
      "type": "llm_generate",
      "config": {
        "prompt": "Based on the following specification, generate python code for a component:\n\n{{component_spec_content}}",
        "model": "{{model|default:'openai/o4-mini'}}",
        "output_format": "files",
        "output_key": "component_code_files"
      }
    },
    {
      "type": "write_files",
      "config": {
        # Prefer using "files_key" over "files" when using LLMGenerateStep with "files" output format
        "files_key": "component_code_files",
        "root": "./output"
      }
    }
  ]
}
```

## Dynamic Output Keys

The output key can be templated to create dynamic storage locations:

```json
{
  "steps": [
    {
      "type": "llm_generate",
      "config": {
        "prompt": "Generate a JSON object with user details.",
        "model": "{{model|default:'openai/o4-mini'}}",
        "output_format": {
          "type": "object",
          "properties": {
            "user": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string"
                },
                "age": {
                  "type": "integer"
                }
              },
              "required": ["name", "age"]
            }
          }
        },
        "output_key": "user_details_{{name}}"
      }
    }
  ]
}
```

## MCP Integration

The LLMGenerateStep can integrate with MCP servers for tool access. The MCP servers can be specified in the `mcp_servers` field of the configuration. The LLM will use these servers to access tools during the generation process.

### MCP Server Configuration Formats

The MCP server configuration can be specified in two formats:

- **HTTP**: For HTTP-based MCP servers, provide:

  - `url`: The URL of the MCP server.
  - `headers`: Optional dictionary of headers to include in the requests.

Example:

```json
{
  "mcp_servers": [
    {
      "url": "http://localhost:3001/sse",
      "headers": {
        "Authorization": "{{token}}"
      }
    }
  ]
}
```

- **STDIO**: For STDIO-based MCP servers, provide:

  - `command`: The command to run the MCP server.
  - `args`: List of arguments for the command.
  - `env`: Optional dictionary of environment variables for the command.
  - `cwd`: Optional working directory for the command.

Example:

```json
{
  "mcp_servers": [
    {
      "command": "python",
      "args": ["-m", "/path/to/mcp_server.py"],
      "env": {
        "MCP_TOKEN": "{{token}}"
      },
      "cwd": "/path/to/mcp"
    }
  ]
}
```

## LLM Output Formats

The LLM can return different formats based on the `output_format` parameter:

- **"text"**: Returns a plain text output.
- **"files"**: Returns a list of `FileSpec` objects, this is provided as a convenience due to the common use case of generating files from LLMs.
- **object**: Returns a JSON object based on the provided JSON schema. The schema is validated before the LLM call, and if invalid, the step will fail.
- **list**: Returns a list of items based on the provided JSON schema. The schema is validated before the LLM call, and if invalid, the step will fail.

### Text Example

Request:

```json
{
  "type": "llm_generate",
  "config": {
    "prompt": "What is the capital of France?",
    "model": "openai/gpt-4o",
    "max_tokens": 100,
    "output_format": "text",
    "output_key": "capital_result"
  }
}
```

Context after execution:

```json
{
  "capital_result": "The capital of France is Paris."
}
```

### Files Example

Request:

```json
{
  "type": "llm_generate",
  "config": {
    "prompt": "Generate Python files for a simple calculator.",
    "model": "openai/o4-mini",
    "output_format": "files",
    "output_key": "calculator_files"
  }
}
```

Context after execution:

```json
{
  "calculator_files": [
    {
      "path": "calculator.py",
      "content": "def add(a, b):\n    return a + b\n\ndef subtract(a, b):\n    return a - b"
    },
    {
      "path": "test_calculator.py",
      "content": "import calculator\n\ndef test_add():\n    assert calculator.add(1, 2) == 3\n\ndef test_subtract():\n    assert calculator.subtract(2, 1) == 1"
    }
  ]
}
```

### Object Example

Request:

```json
{
  "type": "llm_generate",
  "config": {
    "prompt": "Generate a JSON object with user details.",
    "model": "openai/o4-mini",
    "output_format": {
      "type": "object",
      "properties": {
        "user": {
          "type": "object",
          "properties": {
            "name": {
              "type": "string"
            },
            "age": {
              "type": "integer"
            }
          },
          "required": ["name", "age"]
        }
      }
    },
    "output_key": "user_details"
  }
}
```

Context after execution:

```json
{
  "user_details": {
    "user": {
      "name": "Alice",
      "age": 30
    }
  }
}
```

### List Example

Request:

```json
{
  "type": "llm_generate",
  "config": {
    "prompt": "Extract the list of users from this document: {{document_content}}.",
    "model": "openai/o4-mini",
    "output_format": [
      {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "age": {
            "type": "integer"
          }
        },
        "required": ["name", "age"]
      }
    ],
    "output_key": "user_details"
  }
}
```

Context after execution:

```json
{
  "user_details": [
    {
      "name": "Alice",
      "age": 30
    },
    {
      "name": "Bob",
      "age": 25
    }
  ]
}
```
