Packages
Dataset management and caching for AI research benchmarks
Retired package: Deprecated - Use 0.5.0+
Current section
Files
Jump to
Current section
Files
lib/dataset_manager/loader/code.ex
defmodule CrucibleDatasets.Loader.Code do
@moduledoc """
Loader for code generation and understanding datasets.
Supports:
- DeepCoder (agentica-org/DeepCoder-Preview-Dataset)
- HumanEval (openai/human-eval) - uses existing implementation
## Examples
# Load DeepCoder
{:ok, dataset} = CrucibleDatasets.Loader.Code.load(:deepcoder)
"""
alias CrucibleDatasets.Dataset
alias CrucibleDatasets.Fetcher.HuggingFace
require Logger
@datasets %{
deepcoder: %{
repo_id: "agentica-org/DeepCoder-Preview-Dataset",
description: "DeepCoder code generation dataset"
}
}
@doc """
Load a code generation dataset.
## Arguments
* `dataset_name` - Currently supports `:deepcoder`
* `opts` - Options (see below)
## Options
* `:split` - Dataset split (default: "train")
* `:sample_size` - Limit number of items
* `:synthetic` - Use synthetic data for testing (default: false)
* `:token` - HuggingFace API token
"""
@spec load(atom(), keyword()) :: {:ok, Dataset.t()} | {:error, term()}
def load(dataset_name, opts \\ [])
def load(dataset_name, opts) when is_atom(dataset_name) do
case Map.get(@datasets, dataset_name) do
nil ->
{:error, {:unknown_dataset, dataset_name, Map.keys(@datasets)}}
dataset_info ->
synthetic = Keyword.get(opts, :synthetic, false)
if synthetic do
load_synthetic(dataset_name, opts)
else
load_from_huggingface(dataset_name, dataset_info, opts)
end
end
end
defp load_from_huggingface(dataset_name, %{repo_id: repo_id}, opts) do
split = Keyword.get(opts, :split, "train") |> to_string()
sample_size = Keyword.get(opts, :sample_size)
token = Keyword.get(opts, :token)
case HuggingFace.fetch(repo_id, split: split, token: token) do
{:ok, raw_data} ->
items = parse_code_data(raw_data, dataset_name)
items = if sample_size, do: Enum.take(items, sample_size), else: items
dataset =
Dataset.new(
to_string(dataset_name),
"1.0",
items,
%{
source: "huggingface:#{repo_id}",
split: split,
license: "apache-2.0",
domain: "code"
}
)
{:ok, dataset}
{:error, reason} ->
if Application.get_env(:crucible_datasets, :fallback_to_synthetic, false) do
Logger.warning(
"Failed to load #{dataset_name} from HuggingFace: #{inspect(reason)}, falling back to synthetic"
)
load_synthetic(dataset_name, opts)
else
{:error, {:huggingface_fetch_failed, reason}}
end
end
end
defp parse_code_data(raw_data, :deepcoder) do
raw_data
|> Enum.with_index()
|> Enum.map(fn {item, idx} ->
%{
id: "deepcoder_#{idx}",
input: %{
problem: item["problem"] || item["prompt"] || item["instruction"],
language: item["language"] || "python"
},
expected: item["solution"] || item["code"] || item["response"],
metadata: %{
source: item["source"],
difficulty: item["difficulty"],
tags: item["tags"]
}
}
end)
end
defp load_synthetic(dataset_name, opts) do
sample_size = Keyword.get(opts, :sample_size, 20)
items = generate_synthetic_items(sample_size)
dataset =
Dataset.new(
to_string(dataset_name),
"1.0",
items,
%{
source: "synthetic",
license: "apache-2.0",
domain: "code"
}
)
{:ok, dataset}
end
defp generate_synthetic_items(count) do
problems = [
{"Write a function to add two numbers.", "def add(a, b):\n return a + b", "python"},
{"Implement a function to check if a string is a palindrome.",
"def is_palindrome(s):\n return s == s[::-1]", "python"},
{"Write a function to find the factorial of a number.",
"def factorial(n):\n if n <= 1:\n return 1\n return n * factorial(n - 1)",
"python"},
{"Implement a function to reverse a list.", "def reverse_list(lst):\n return lst[::-1]",
"python"},
{"Write a function to find the maximum element in a list.",
"def find_max(lst):\n return max(lst)", "python"}
]
for i <- 0..(count - 1) do
{problem, solution, language} = Enum.at(problems, rem(i, length(problems)))
%{
id: "code_#{i}",
input: %{
problem: problem,
language: language
},
expected: solution,
metadata: %{
source: "synthetic",
difficulty: "easy"
}
}
end
end
@doc """
List available code datasets.
"""
@spec available_datasets() :: [atom()]
def available_datasets, do: Map.keys(@datasets)
end