Goal: Build a publicly visible track record as a serious AI Engineer through real open source contributions — merged PRs, issue discussions, and community presence in the AI/ML ecosystem. Target companies: Google DeepMind · Anthropic · OpenAI · Microsoft · HuggingFace · Cohere · Mistral
This is not just a PR challenge. This is a career strategy. Each phase builds on the last. By Phase 5, your GitHub profile tells a story that gets you interviews at top AI companies.
Phase 1 → Learn the workflow, build presence [DONE ✅]
Phase 2 → Get real merges, build reputation [IN PROGRESS 🔄]
Phase 3 → Fix real bugs, become trusted [NEXT]
Phase 4 → Own features, get credited in changelogs [GOAL]
Phase 5 → Core contributor, public recognition [VISION]
Goal: Understand how open source works. Learn repo rules, CI systems, PR etiquette, and docstring styles across 15+ repos. Build the habit of daily contribution.
Strategy used: Add missing docstrings to public utility functions in ruff-only repos.
What we learned:
- Large HuggingFace repos (smolagents, evaluate, accelerate, datasets, optimum) have slow review cycles for doc-only PRs
- Repos with strict rules (wandb, LangChain) require different approach — file issues first, wait for assignment
- click maintainers close tiny PRs silently — need more substance
- Joblib, lighteval, nanotron, stanza, optax have active maintainers who review quickly
Phase 1 result: 35 PRs opened · 1 merged (#3843) · 28 active open · 30 log files · 15 repos touched
Phase 1 PRs:
| Day | Date | Repo | Type | PR | Status |
|---|---|---|---|---|---|
| 1 | 2026-06-29 | vonzosten/awesome-LangGraph | Add 2 community projects | #76 | ⏳ Open |
| 1 | 2026-06-29 | langchain-ai/langchain | Bug fix — Visitor._validate_func error message |
#38538 | 🔄 Closed → awaiting assignment on #36701 |
| 1 | 2026-06-29 | langchain-ai/langchain | Docstring — missing await in qdrant + chroma |
#38539 | 🔄 Closed → awaiting #37058 |
| 1 | 2026-06-29 | langchain-ai/langchain | Docstring — clarify JSON schema title requirement |
#38542 | 🔄 Closed → awaiting #34662 |
| 1 | 2026-06-29 | langchain-ai/langchain | Bug fix — InMemoryCache eviction + Language.PERL |
#38543 | 🔄 Closed → awaiting #36750 |
| 2 | 2026-06-30 | vibrantlabsai/ragas | Bug fix — NonLLMContextRecall threshold > → >= + tests |
#2798 | ⏳ Open |
| 3 | 2026-06-30 | huggingface/smolagents | Docs — 5 missing docstrings in utils.py |
#2438 | ⏳ Open |
| 4 | 2026-06-30 | huggingface/evaluate | Docs — 5 missing docstrings in naming.py |
#771 | ⏳ Open |
| 5 | 2026-06-30 | huggingface/accelerate | Docs — 3 missing docstrings in operations.py |
#4095 | ⏳ Open |
| 6 | 2026-06-30 | huggingface/datasets | Docs — 5 missing docstrings in py_utils.py |
#8294 | ⏳ Open |
| 7 | 2026-06-30 | huggingface/optimum | Docs — 5 missing docstrings in testing_utils.py + save_utils.py |
#2454 | ⏳ Open |
| 8 | 2026-06-30 | huggingface/sentence-transformers | Docs — to_scipy_coo in util/tensor.py (trimmed from Dense methods per review) |
#3843 | ✅ MERGED |
| 9 | 2026-06-30 | huggingface/safetensors | Docs — storage_ptr, storage_size, rename, check_file_size |
#806 | ⏳ Open |
| 10 | 2026-06-30 | nltk/nltk | Docs — 5 missing docstrings in compat.py + decorators.py |
#3688 | ⏳ Open |
| 11 | 2026-06-30 | wandb/wandb | Docs — 7 env helper functions in env.py |
#12133 | 🚫 Closed — anti-AI-PR policy |
| 12 | 2026-07-01 | explosion/spaCy | Docs — 6 functions in util.py + cli/_util.py |
#13987 | ⏳ Open |
| 13 | 2026-07-02 | pallets/click | Docs — measure_table + iter_rows in formatting.py |
#3659 | 🚫 Closed — too minor |
| 14 | 2026-07-03 | joblib/joblib | Docs — format_time, short_format_time, pformat |
#1811 | ⏳ Open |
| 15 | 2026-07-03 | huggingface/lighteval | Docs — 3 functions in utils/imports.py |
#1282 | ⏳ Open |
| 16–30 | 2026-07-04 | nanotron · paramiko · lm-eval-harness · numba · stanza · optax | Docs — missing docstrings across utility files | #407 #408 #409 #2641 #3909 #3910 #10686 #1634 #1635 #1636 #1720 #1721 | ⏳ Open |
Goal: At least 10 merged PRs. Shift from docstrings to higher-value contributions: fixing broken examples in docs, adding missing type annotations, writing tests for untested public functions.
Why this phase matters: A GitHub profile with 0 merges looks like spam to recruiters. 10 merges across well-known AI repos (HuggingFace, EleutherAI, StanfordNLP) signals you are a real contributor, not just a PR opener.
Strategy shift — 3 types of contributions that get merged fast:
Many repos have docstring examples that are outdated or actually fail if you run them. These get merged same-day because they are objectively wrong, not a style opinion.
- How to find:
grep -r ">>>" src/then copy-paste examples into Python and run them - Target repos: ragas, smolagents, sentence-transformers, lm-evaluation-harness
Find public functions with 0 test coverage. Write simple unit tests. Maintainers almost never reject tests.
- How to find:
pytest --cov=src --cov-report=term-missing→ look for 0% covered public functions - Target repos: lighteval, nanotron, optax, stanza
Every active repo has a good first issue label. These are bugs the maintainer has already accepted — they just need someone to fix them.
- How to find:
gh issue list --repo OWNER/REPO --label "good first issue" --state open - Target repos: ragas, smolagents, lm-evaluation-harness, sentence-transformers
Phase 2 target repos (pre-verified safe):
| Repo | Why | Focus |
|---|---|---|
| vibrantlabsai/ragas | Small team, fast reviews, AI domain | Good first issues + broken examples |
| huggingface/smolagents | HF flagship agentic lib, active | Broken examples in docstrings |
| EleutherAI/lm-evaluation-harness | THE benchmark suite, high visibility | Tests + good first issues |
| stanfordnlp/stanza | Active NLP team, responsive | Tests for untested functions |
| google-deepmind/optax | DeepMind repo, high profile | Broken examples |
| huggingface/lighteval | Eval framework, small team | Tests + good first issues |
| joblib/joblib | scikit-learn ecosystem, very active | Good first issues |
Phase 2 daily workflow:
- Morning: check if any Phase 1 PRs got merged or commented → respond within 1 hour
- Pick today's contribution type (A, B, or C) from the list above
- Do the contribution — must be more substantial than Phase 1 (aim for 20+ lines changed)
- Open PR, update log, commit
Phase 2 scoreboard:
| Day | Date | Repo | Type | PR | Status |
|---|---|---|---|---|---|
| 31 | 2026-07-04 | huggingface/evaluate | Bug fix — export EvaluationModuleError, wrap _compute failures (fixes #758) |
#774 | ⏳ Open |
| 32 | 2026-07-05 | huggingface/smolagents | Bug fix — replace assert with explicit check in _validate_final_answer + test (fixes #2456) |
#2469 | ⏳ Open |
| 33 | 2026-07-06 | joblib/joblib | Bug fix — accept any os.PathLike in dump() + load(), not just pathlib.Path + test (fixes #1784) |
#1812 | ⏳ Open |
| 34 | 2026-07-11 | joblib/joblib | Review response — addressed maintainer comments on #1811 (docstring spacing) and #1812 (dropped logger.py overlap, os.PathLike docstrings) |
#1811 · #1812 | ⏳ Open |
| 35 | 2026-07-11 | nltk/nltk | Test coverage — regression tests for untested transitive_closure in util.py (chain, reflexive, cycle, empty, no-mutation + set-identity) |
#3703 | ✅ MERGED |
| 36 | 2026-07-11 | UKPLab/sentence-transformers | Test coverage — regression tests for untested append_to_last_row in util/misc.py (append, multi-value, header-only + empty no-op) |
#3855 | ✅ MERGED |
| 37 | 2026-07-11 | joblib/joblib | Test coverage — regression tests for untested format_time + short_format_time in logger.py (both branches, cross-platform via _squeeze_time) |
#1814 | ⏳ Open |
| 38 | 2026-07-11 | explosion/spaCy | Test coverage — regression tests for untested get_minor_version_range, get_base_version, split_requirement in util.py (+ signed contributor agreement, first PR) |
#13991 | ⏳ Open |
| 39 | 2026-07-11 | stanfordnlp/stanza | Test coverage — regression tests for untested harmonic_mean + get_adaptive_eval_interval in common/utils.py (weighted/zero/assert + banker's-rounding edge) |
#1641 | ❌ Closed — maintainer flagged as spam |
| 40 | 2026-07-11 | huggingface/evaluate | Code fix — remove mutable default arg (invert_range=[] → None + guard) in radar_plot |
#781 | ⏳ Open |
| 41 | 2026-08-03 | huggingface/sentence-transformers | Review response — trimmed #3843 to to_scipy_coo per maintainer, rebased off 30-commit drift, matched util/ docstring style, re-requested review |
#3843 | ✅ MERGED |
| 42 | 2026-08-04 | nltk/nltk | Review response — strengthened the non-mutation test on #3703 to assert set identity (not just equality) after ekaf raised the unresolved review concern; mutation-tested that the old assertion missed a rebind |
#3703 | ✅ MERGED |
| 43 | 2026-07-27 | py-pdf/pypdf | Bug fix — 2/4-bit /DeviceRGB images forced to palette mode left an unrecognized Pillow mode and broke extraction (#3924); now unpacks interleaved colour components (colors=) and scales them to full range (scale=) |
#3929 | ✅ MERGED |
| 44 | 2026-08-04 | py-pdf/pypdf | Review response — took maintainer's int(mode[0]) suggestion, proved the new bits2byte params survive a general fix, then rebased off the _handle_flate reorder (#3904) to clear the merge conflict |
#3929 | ✅ MERGED |
| 45 | 2026-08-04 | py-pdf/pypdf | Bug fix — follow-up to #3929: low-bit expansion only ran for FlateDecode, so unfiltered/inline images passed a raw "4bits" mode to Pillow and raised unrecognized image mode; extracted _expand_low_bit_samples() and applied it to all three raw-bytes paths |
#3938 | ✅ MERGED |
| 47 | 2026-08-05 | run-llama/llama_index | Bug fix (51k★) — BaseComponent.__getstate__ deleted unpickleable attributes from the live object, not a copy: pydantic returns self.__dict__ by reference, so pickling silently corrupted the source object (surfaces later in caching / deepcopy / multiprocessing paths). Shallow-copy before pruning; fixed the private-attr path too |
#22592 | ⏳ Open |
| 46 | 2026-08-05 | mpdavis/python-jose | Security fix — RSA1_5 JWE padding oracle (RFC 7516 §11.5): PKCS1v15's constant-time path returns wrong-length bytes for ~68% of malformed keys, bypassing random-CEK substitution and producing a distinguishable length error. Same class as Authlib CVE-2026-28490. 400 malformed tokens: 297/103 split → uniform | #415 | ⏳ Open |
Goal: 5+ bug fix PRs merged in AI repos. Start appearing in changelogs. Get maintainers to know your name.
Why this phase matters: Recruiters at Anthropic, Google DeepMind, and HuggingFace look at what you fixed, not just what you documented. A merged bug fix in lm-evaluation-harness or ragas says "this person understands the codebase deeply."
Strategy:
- Spend 2–3 days per week reading issues carefully in 3–4 repos
- Reproduce bugs locally before claiming them
- Write a clear fix + regression test
- Comment on the issue explaining your approach before opening a PR
- Build a relationship with 2–3 maintainers through issue discussions
Target contribution types:
- Fix metric calculation bugs in RAG evaluation libraries (ragas, lighteval)
- Fix edge cases in tokenization and data loading (datasets, stanza)
- Fix incorrect behavior in distributed training utilities (nanotron, accelerate)
- Add missing error handling in agent frameworks (smolagents, lm-evaluation-harness)
Phase 3 target repos:
| Repo | Domain relevance | Difficulty |
|---|---|---|
| vibrantlabsai/ragas | RAG evaluation — core AI skill | Medium |
| huggingface/smolagents | AI agents — hot topic | Medium |
| EleutherAI/lm-evaluation-harness | LLM benchmarking | Medium-Hard |
| huggingface/lighteval | LLM evaluation | Medium |
| huggingface/datasets | Data loading | Medium |
Phase 3 goal: 5 merged bug fixes · First changelog entry · Known by name to at least 2 maintainers
Goal: Own a small but complete feature end-to-end in 1–2 repos. Get credited in release notes.
Why this phase matters: "Contributed feature X to repo Y" on a CV beats "fixed 50 docstrings." By Phase 4, you want 1–2 sentences in a release changelog that say your name.
Strategy:
- Pick 1–2 repos where you are already known from Phase 2–3 PRs
- Find a well-scoped feature request (not too large, clearly wanted)
- Discuss approach on the issue before writing code
- Implement, write tests, update docs — complete package
- Be responsive to review feedback — iterate fast
Target feature ideas (AI-domain, manageable scope):
- Add a new metric to
ragas(e.g. answer completeness with configurable LLM) - Add a new task/benchmark to
lm-evaluation-harness(e.g. a Hindi reasoning dataset) - Add async support to a sync-only function in
smolagents - Add a new callback type to
lightevalfor custom logging - Improve streaming output handling in
nanotron
Phase 4 goal: 1–2 features merged · Named in changelog · GitHub profile shows "contributed to X, Y"
Goal: Become a recognized contributor in 1 repo. Get invited to review others' PRs. Speak or write about your contributions.
Why this phase matters: Top AI companies (Anthropic, Google DeepMind, HuggingFace) hire people who are already part of the community. If a hiring manager recognizes your GitHub handle from a repo they use daily, the interview starts differently.
Strategy:
- Focus entirely on 1–2 repos where you have the most merged PRs
- Start reviewing other people's PRs — leave thoughtful, constructive comments
- Write a blog post or LinkedIn article: "What I learned from contributing to [repo]" — link your PRs
- File issues proactively — not just fixes, but ideas for improvement
- Apply for maintainer status if the repo has a formal process
Phase 5 goal:
- Invited to review PRs in at least 1 repo
- Written 1 public post about your open source journey
- GitHub profile: 20+ merged PRs across 5+ AI repos
- At least 1 maintainer who can vouch for you in a reference
As an AI Engineer targeting top companies, here is what each phase adds to your story:
| Phase | What a recruiter sees | What it signals |
|---|---|---|
| 1 | 30+ PRs opened, daily contributions | Consistency, knows the workflow |
| 2 | 10+ merged PRs across HF, EleutherAI, StanfordNLP | Can actually ship, not just open PRs |
| 3 | Bug fixes with tests in AI eval frameworks | Understands codebases deeply, writes tests |
| 4 | Feature in changelog of known AI library | Can own a task end-to-end |
| 5 | Reviewer in a top AI repo, blog post | Part of the community, trusted |
The portfolio you are building here answers the one question every top company has: "Can this person contribute to our codebase on day one?"
Your GitHub will say yes — with receipts.
- Phase: Phase 2 — Days 31–60
- Total PRs opened: 48
- Total PRs merged: 7 — joblib #1811 · joblib #1812 · sentence-transformers #3855 · sentence-transformers #3843 · nltk #3703 · pypdf #3929 · pypdf #3938 ← 2 real bug fixes in pypdf
- PRs closed by bot: 5 (LangChain — requires issue assignment)
- PRs closed by maintainer: 8 (wandb · click · stanza ×4 · nltk · joblib #1814)
- Active open PRs: 26
- LangChain issues awaiting assignment: 5
- LangGraph issues awaiting assignment: 4
| Issue | Fix | Status |
|---|---|---|
| #36701 | Bug: comparators → operators in Visitor._validate_func + 4 unit tests |
⏳ Awaiting assignment |
| #37058 | Docstring: missing await in qdrant asimilarity_search example |
⏳ Awaiting assignment |
| #38560 | Docstring: missing await in InMemoryVectorStore + Chroma examples |
⏳ Awaiting assignment |
| #34662 | Docstring: clarify title is required key in JSON schema dicts |
⏳ Awaiting assignment |
| #36750 | Bug: InMemoryCache eviction guard + add Language.PERL separators |
⏳ Awaiting assignment |
| Issue | Fix | Status |
|---|---|---|
| #8130 | Typo: GraphRecusionError → GraphRecursionError in docstring |
⏳ Awaiting assignment |
| #8226 | Grammar: tool_calls → tool_call in mermaid diagram |
⏳ Awaiting assignment |
| #8227 | Docs: context_schema param missing description |
⏳ Awaiting assignment |
| #8228 | Wrong import: from langchain.tools import ToolNode in 2 places |
⏳ Awaiting assignment |
wandb · peft · trl · litellm · diffusers · huggingface_hub · tokenizers · pytorch · keras · scikit-learn · openai-python · haystack · mlflow · scikit-image · chroma · transformers · rich · timm · instructor · gradio · networkx · pytest · click · attrs
smolagents · evaluate · accelerate · datasets · optimum · sentence-transformers · safetensors · spaCy · joblib · lighteval · nanotron · paramiko · lm-evaluation-harness · numba · stanza · optax · ragas
All daily logs at logs/ — one file per day with full context, what was changed, why, and lessons learned.
Started: 2026-06-29 | Maintained by Chandan Kumar (RavSinghChandan) Target: Top AI Engineer role at Google DeepMind · Anthropic · HuggingFace · Cohere