Current section
Files
Jump to
Current section
Files
lib/mix/tasks/arcana.eval.generate.ex
defmodule Mix.Tasks.Arcana.Eval.Generate do
@shortdoc "Generate synthetic test cases for retrieval evaluation"
@moduledoc """
Generates synthetic test cases from existing chunks.
## Usage
mix arcana.eval.generate --sample-size 50
mix arcana.eval.generate --source-id my-docs --sample-size 100
mix arcana.eval.generate --collection my-collection
## Options
* `--sample-size` - Number of chunks to sample (default: 50)
* `--source-id` - Limit to chunks from specific source
* `--collection` - Limit to chunks from specific collection
## Configuration
Requires `:repo` and `:llm` to be configured in your application:
config :arcana,
repo: MyApp.Repo,
llm: my_llm_function
"""
use Mix.Task
@impl Mix.Task
def run(args) do
Mix.Task.run("app.start")
{opts, _, _} =
OptionParser.parse(args,
strict: [sample_size: :integer, source_id: :string, collection: :string]
)
sample_size = Keyword.get(opts, :sample_size, 50)
source_id = Keyword.get(opts, :source_id)
collection = Keyword.get(opts, :collection)
repo = Application.get_env(:arcana, :repo) || raise "Missing :arcana, :repo config"
llm = Application.get_env(:arcana, :llm) || raise "Missing :arcana, :llm config"
IO.puts("Generating test cases from #{sample_size} chunks...")
generation_opts =
[repo: repo, llm: llm, sample_size: sample_size]
|> maybe_add(:source_id, source_id)
|> maybe_add(:collection, collection)
case Arcana.Evaluation.generate_test_cases(generation_opts) do
{:ok, test_cases} ->
IO.puts("Generated #{length(test_cases)} test cases")
{:error, reason} ->
IO.puts("Failed: #{inspect(reason)}")
exit({:shutdown, 1})
end
end
defp maybe_add(opts, _key, nil), do: opts
defp maybe_add(opts, key, value), do: Keyword.put(opts, key, value)
end