# `LeXtract.Prompting`
[🔗](https://github.com/YgorCastor/lextract.git/blob/main/lib/lextract/prompting.ex#L1)

Prompt generation for LLM extraction.

Creates structured prompts with few-shot examples to guide the LLM
in extracting entities from text in the desired format.

## Examples

    iex> template = %{
    ...>   description: "Extract medications from clinical text",
    ...>   examples: [
    ...>     %{
    ...>       text: "Patient takes aspirin",
    ...>       extractions: [
    ...>         %{extraction_class: "medication", extraction_text: "aspirin"}
    ...>       ]
    ...>     }
    ...>   ]
    ...> }
    iex> handler = LeXtract.FormatHandler.new(:json)
    iex> generator = LeXtract.Prompting.new(template, handler)
    iex> is_struct(generator, LeXtract.Prompting)
    true

# `t`

```elixir
@type t() :: %LeXtract.Prompting{
  answer_prefix: String.t(),
  examples_heading: String.t(),
  format_handler: LeXtract.FormatHandler.t(),
  question_prefix: String.t(),
  template: template()
}
```

# `template`

```elixir
@type template() :: %{
  description: String.t(),
  examples: [LeXtract.Document.example()]
}
```

# `format_example`

```elixir
@spec format_example(t(), LeXtract.Document.example()) :: String.t()
```

Formats a single example as text (Q&A format).

Converts an example into:
Q: <example text>
A: <formatted extractions in JSON/YAML>

## Examples

    iex> template = %{description: "Extract", examples: []}
    iex> handler = LeXtract.FormatHandler.new(:json)
    iex> generator = LeXtract.Prompting.new(template, handler)
    iex> example = %{text: "John Doe", extractions: [%{entity: "John Doe"}]}
    iex> formatted = LeXtract.Prompting.format_example(generator, example)
    iex> String.contains?(formatted, "Q: John Doe")
    true

# `new`

```elixir
@spec new(template(), LeXtract.FormatHandler.t(), keyword()) :: t()
```

Creates a new prompt generator.

## Parameters

  * `template` - Prompt template with description and examples
  * `format_handler` - Format handler for JSON/YAML output
  * `opts` - Options (see below)

## Options

  * `:examples_heading` - Heading text for examples section (default: "Examples")
  * `:question_prefix` - Prefix for question lines (default: "Q: ")
  * `:answer_prefix` - Prefix for answer lines (default: "A: ")

## Examples

    iex> template = %{description: "Extract entities", examples: []}
    iex> handler = LeXtract.FormatHandler.new(:json)
    iex> generator = LeXtract.Prompting.new(template, handler)
    iex> generator.examples_heading
    "Examples"

    iex> template = %{description: "Extract entities", examples: []}
    iex> handler = LeXtract.FormatHandler.new(:yaml)
    iex> generator = LeXtract.Prompting.new(template, handler, examples_heading: "Few-shot Examples")
    iex> generator.examples_heading
    "Few-shot Examples"

# `read_template`

```elixir
@spec read_template(Path.t(), :json | :yaml) ::
  {:ok, template()} | {:error, Exception.t()}
```

Reads a prompt template from a JSON or YAML file.

## Parameters

  * `path` - File path to template
  * `format` - :json or :yaml

## Returns

`{:ok, template}` or `{:error, exception}`

## Examples

    iex> File.write!("/tmp/test_template.json", ~s({"description": "Test", "examples": []}))
    iex> {:ok, template} = LeXtract.Prompting.read_template("/tmp/test_template.json", :json)
    iex> template.description
    "Test"
    iex> File.rm("/tmp/test_template.json")
    :ok

# `render`

```elixir
@spec render(t(), String.t(), keyword()) :: String.t()
```

Renders a complete prompt for the LLM.

Combines:
- Template description
- Optional additional context
- Few-shot examples (formatted)
- The question text
- Answer prefix to guide LLM response

## Parameters

  * `generator` - The prompt generator
  * `question` - Text to extract from
  * `opts` - Options (see below)

## Options

  * `:additional_context` - Extra context to include before examples

## Returns

String prompt ready to send to LLM.

## Examples

    iex> template = %{description: "Extract people", examples: []}
    iex> handler = LeXtract.FormatHandler.new(:json)
    iex> generator = LeXtract.Prompting.new(template, handler)
    iex> prompt = LeXtract.Prompting.render(generator, "John Doe works here")
    iex> String.contains?(prompt, "Extract people")
    true
    iex> String.contains?(prompt, "Q: John Doe works here")
    true

---

*Consult [api-reference.md](api-reference.md) for complete listing*
