Lotus.AI.Prompts.QueryGeneration (Lotus v1.0.0)

Copy Markdown View Source

System prompts for query generation.

Prompts are assembled in a fixed order so that core Lotus rules (the {{var}} / [[...]] template DSL, the response contract, the workflow instructions) always precede adapter-contributed content (the ai_context.syntax_notes and :example_query). Untrusted adapters have their free-form fields stripped upstream in Lotus.Source.Adapter.ai_context/1; placing core content first means a compromised adapter cannot override the Lotus DSL rules through later text.

Summary

Functions

Extract both the statement and its variables from LLM response content.

Extract the generated statement from LLM response content.

Extract variable configurations from LLM response content.

Generate system prompt for query generation.

Functions

extract_response(content)

@spec extract_response(String.t()) ::
  {:ok, %{statement: String.t(), variables: [map()]}}
  | {:error, {:unable_to_generate, String.t()}}

Extract both the statement and its variables from LLM response content.

Combines extract_statement/1 and extract_variables/1 into a single call. This is the primary extraction entry point for response parsing.

Parameters

  • content - Raw response content from the LLM

Returns

  • {:ok, %{statement: String.t(), variables: [map()]}} - Successfully extracted
  • {:error, {:unable_to_generate, reason}} - LLM refused to generate

Examples

iex> extract_response("```sql\nSELECT * FROM users WHERE status = {{status}}\n```\n```variables\n[{\"name\": \"status\"}]\n```")
{:ok, %{statement: "SELECT * FROM users WHERE status = {{status}}", variables: [...]}}

extract_statement(content)

@spec extract_statement(String.t()) ::
  {:ok, String.t()} | {:error, {:unable_to_generate, String.t()}}

Extract the generated statement from LLM response content.

Accepts any fence label, since the prompt asks for the adapter's language family, and detects when the LLM has refused to generate.

Parameters

  • content - Raw response content from the LLM

Returns

  • {:ok, statement} - Successfully extracted statement
  • {:error, {:unable_to_generate, reason}} - LLM refused to generate

Examples

iex> extract_statement("```sql\nSELECT * FROM users\n```")
{:ok, "SELECT * FROM users"}

iex> extract_statement("UNABLE_TO_GENERATE: This is a weather question")
{:error, {:unable_to_generate, "This is a weather question"}}

extract_variables(content)

@spec extract_variables(String.t()) :: [map()]

Extract variable configurations from LLM response content.

Parses a ```variables JSON block from the response. Returns an empty list if no block is found or if the JSON is malformed.

Parameters

  • content - Raw response content from the LLM

Returns

List of variable configuration maps (empty list if none found).

Examples

iex> extract_variables("```variables\n[{\"name\": \"status\", \"type\": \"text\"}]\n```")
[%{"name" => "status", "type" => "text", "widget" => "input", "list" => false}]

iex> extract_variables("Just a statement without variables")
[]

system_prompt(ai_context, table_names, opts \\ [])

@spec system_prompt(map(), [String.t()], keyword()) :: String.t()

Generate system prompt for query generation.

Composition order

Each section is emitted in this order to establish the trust boundary:

  1. System role (core)
  2. Read-only / write-only instructions (core)
  3. Available tables (core, schema context)
  4. Tools + workflow (core)
  5. Lotus template DSL rules (core, immutable — lotus_template_notes/0 + Variables.system_docs/1)
  6. Adapter syntax_notes (filtered if untrusted, truncated at 1 KB)
  7. Adapter example_query (bounded at 2 KB)
  8. Output contract examples (core)

Parameters

  • ai_context — the sanitized map returned by Lotus.Source.Adapter.ai_context/1 (:language, :example_query, :syntax_notes, :error_patterns).
  • table_names — list of available table names.
  • opts — keyword list:
    • :read_only — when true (default), instruct the LLM to stick to read-only statements.