← TinyGPT · docs · devlog · roadmap · speedup
source: docs/github_data_integration.md · view on GitHub ↗

GitHub data integration

tinygpt fetch-github pulls structured training data from GitHub for the code-specialist agent track (debugger, reviewer, commit-message generator). It is the GitHub-side counterpart to tinygpt download-dataset (HuggingFace Hub).

Why this matters. HuggingFace gives you pre-curated datasets; GitHub gives you the in-the-wild signal that nobody has packaged yet. Issue→PR pairs are the training data for a debugger agent: “user reported X, here is the diff that fixed it”. Review-comment pairs are the training data for a PR-reviewer agent. Commit-message pairs train a “write a commit message for this diff” model. All three live on GitHub, all three are huge, and all three were missing from tinygpt’s data pipeline before this module.


Quick start

# Set your token (5000 req/h vs 60 without — huge difference).
export GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxx

# Issue→PR pairs from a smallish repo, capped at 50 records.
tinygpt fetch-github pallets/flask --kind issues-prs --limit 50

# Commits from rust-lang/rust since 2024 — commit-message training.
tinygpt fetch-github rust-lang/rust --kind commits \
    --since 2024-01-01T00:00:00Z --limit 5000 \
    --out rust.commits.jsonl

# PR review comments — reviewer-agent training signal.
tinygpt fetch-github huggingface/transformers --kind reviews --limit 500

# Browse the curated GitHub recipes for a specialist.
tinygpt list-datasets --specialist debugger
# (will list HF datasets first, then the curated GitHub recipes)

Output lands in the JSONL file passed to --out (or ./<owner>__<repo>.<kind>.jsonl by default).


CLI flags

FlagMeaningDefault
<owner/repo>positional repo to fetch fromrequired
--kindissues-prs | reviews | commitsissues-prs
--labelGitHub issue label filterbug (for issues-prs only)
--stateopen | closed | allclosed
--sinceISO 8601 timestamp; updated-afterunset
--max-diff-bytestruncate diffs above N chars10000
--limitmax records to emit1000
--outoutput JSONL path./<repo>.<kind>.jsonl
--multi-reponewline-separated repo list to aggregateunset
--resumeskip records already present in --outoff
--dry-runprint plan, no fetchoff

Output formats

All three record kinds use the same outer shape so they drop into tinygpt sft without extra adapters:

{ "instruction": "...", "response": "...", "metadata": { ... } }

metadata carries provenance (repo, issue/PR/commit number, labels, kind) so downstream filtering can dedupe / weight / license-check. tinygpt sft ignores metadata and consumes only instruction + response.

issues-prs — bug fix training

{
  "instruction": "<issue title>\n\n<issue body>",
  "response": "<PR description>\n\n--- diff ---\n<unified diff (possibly truncated)>",
  "metadata": {
    "repo": "owner/repo",
    "issue_number": 123,
    "pr_number": 124,
    "labels": ["bug", "regression"],
    "kind": "issue-pr",
    "files_changed": 3
  }
}

reviews — PR reviewer training

{
  "instruction": "review this code:\n<diff hunk>",
  "response": "<reviewer's comment>",
  "metadata": {
    "repo": "owner/repo",
    "pr_number": 124,
    "comment_id": 8675309,
    "file": "src/foo.py",
    "kind": "review"
  }
}

commits — commit message training

{
  "instruction": "<diff>",
  "response": "<commit message>",
  "metadata": {
    "repo": "owner/repo",
    "sha": "abc123...",
    "files_changed": 5,
    "kind": "commit"
  }
}

GitHub token setup

GitHub’s REST API has two rate limits:

Create a token at https://github.com/settings/tokens and set:

export GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxx

Scopes:

The tool reads the env var via ProcessInfo.processInfo.environment. It runs without a token but prints a clear warning and you will hit the 60/h ceiling fast.

Rate-limit handling

The client reads two response headers:

A 403 with "rate limit" in the body or any 429 is surfaced as GHError.rateLimited with the reset time — the CLI prints a clear message rather than throwing a raw HTTP error.


Issue → PR linkage heuristic

GitHub does not have a first-class “this PR closes that issue” pointer in REST (it does in GraphQL, but we don’t depend on that). We resolve the linkage in two layers:

  1. Timeline eventsGET /repos/{owner}/{repo}/issues/{n}/timeline returns a stream of events. For each cross-referenced event whose source.issue.pull_request is present, we extract the PR number from source.issue.pull_request.url. This is the high-recall path; it picks up PRs whether they say “Fixes #” or not, as long as a PR referenced the issue.
  2. Body regex fallback — if no timeline hit, we scan the issue body for Closes #N / Fixes #N / Resolves #N (and the closed:, fix, resolve variants), and the same with owner/repo#N. We accept only the current repo’s references to avoid noise from cross-repo links.

If neither path resolves, the record is skipped and counted in Stats.skippedNoPR. Closed-by-direct-commit issues (no PR involved, common in projects with merge-commit workflows) are dropped — they’re not useful training signal for a PR-writer agent.


Resume + caching


Curated recipes

tinygpt list-datasets --specialist debugger (or --specialist code) prints both the HF datasets and the GitHub recipes — a hand-picked set of repos that have well-labelled bug trackers, “Fixes #N” PR discipline, and permissive licenses. The shortlist lives in native-mac/Sources/TinyGPTData/DatasetRegistry.swift under GitHubRecipes.all.

Current entries (subject to growth):

RepoLanguageRecommended kindsLicense
pytorch/pytorchpython/c++issues-prs, commitsBSD-3
huggingface/transformerspythonissues-prs, reviews, commitsApache-2
tensorflow/tensorflowpython/c++issues-prs, commitsApache-2
numpy/numpypython/cissues-prs, commitsBSD-3
scikit-learn/scikit-learnpythonissues-prsBSD-3
rust-lang/rustrustissues-prs, reviews, commitsMIT/Apache-2
tokio-rs/tokiorustissues-prs, commitsMIT
django/djangopythonissues-prs, commitsBSD-3
pallets/flaskpythonissues-prsBSD-3
pandas-dev/pandaspythonissues-prs, commitsBSD-3
golang/gogoissues-prs, commitsBSD-3
nodejs/nodejavascript/c++issues-prs, reviewsMIT
vuejs/coretypescriptissues-prsMIT

Adding a recipe: edit GitHubRecipes.all in DatasetRegistry.swift. Pick repos with:


Caveats


File layout

native-mac/Sources/TinyGPTData/GitHubAPI.swift      REST client (URLSession + pagination + rate-limit)
native-mac/Sources/TinyGPTData/GitHubCorpus.swift   issue→PR / reviews / commits extractor
native-mac/Sources/TinyGPTData/DatasetRegistry.swift  GitHubRecipes.all (added)
native-mac/Sources/TinyGPT/FetchGitHub.swift        CLI subcommand
native-mac/Sources/TinyGPT/TinyGPT.swift            pre-switch shim wires `fetch-github`
docs/github_data_integration.md                     (this file)

The CLI is wired through the same pre-switch shim pattern as download-dataset and list-datasets (see TinyGPT.swift’s TODO(github-data-merge) marker) so concurrent agents working on the main switch block don’t merge-conflict.