Dev.to AI πŸ€– Ai πŸ‘ 0 πŸ“– 9 min read

Duplicate of #...: an open model that remembers 23,000 GitHub issues so maintainers don't have to

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady What I Built The laziest comment in open source is four words long: β€œDuplicate of #1234.” Paste it, and GitHub links

Duplicate of #...: an open model that remembers 23,000 GitHub issues so maintainers don't have to

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady

What I Built

The laziest comment in open source is four words long: β€œDuplicate of #1234.” Paste it, and GitHub links the two issues and closes the new one.

It is only lazy if you already know #1234 exists. In zed-industries/zed, maintainers have written it 1,653 times, and the issue they pointed to was filed a median of 1,343 issues (64 days) earlier. Nobody remembers that far back. So every duplicate is a search through a tracker with thousands of open issues, or a contributor fixing a bug that already has a thread, a workaround and a PR somewhere else.

Already Filed remembers for you. Point it at a GitHub repo and an open model, running in your browser tab, reads every open issue (and every one closed in the last 30 days), then lists the open issues that say the same thing as an earlier one. Each comes with the earlier issues it most resembles and a button that copies β€œDuplicate of #…”. It suggests; you decide.

It works the other way too: paste the issue you are about to file, and it shows you whether someone got there first.

Already Filed on a snapshot of ollama/ollama: 51 of 2,585 open issues flagged, each shown next to the earlier issue it most resembles, with a button to copy

Who gets to be lazier: maintainers on triage duty, and anyone about to file a bug who would rather not be told β€œdupe” by a bot an hour later.

Demo

πŸ”— vanshajpoonia.github.io/already-filed

No sign-up, no API key. Press ollama/ollama (instant snapshot) to open a snapshot of ollama's 2,711 open and recently closed issues, read in advance by the same model, so you see results straight away. On that snapshot it flags 51 of 2,585 open issues as probably filed before: two requests for the same Rockchip NPU, two for a Windows portable mode, three reports of the Mac app stuck on β€œLoading…”, and a run of Apple M5 Metal shader crashes.

Or type any public repo and press Find the duplicates to read it live. The model (197 MB) downloads once. After that, ollama's 2,714 open and recently closed issues take about five minutes on my laptop: 45 seconds to fetch them from GitHub, four minutes to read them on the GPU, and a few seconds to compare.

Code

GitHub logo VanshajPoonia / already-filed

Finds the open GitHub issues that were already filed. EmbeddingGemma reads every issue in your browser; tested against every duplicate maintainers linked in zed and neovim.

Already Filed πŸ¦₯

Finds the open GitHub issues that say the same thing as an earlier one, so maintainers can type β€œDuplicate of #…” without remembering thousands of issues. And lets a reporter check before filing.

Point it at a repo. EmbeddingGemma, Google's open-weight embedding model, reads every open issue (and every one closed this month) in your browser, and the page lists the open issues that look like one filed before, with the comment ready to copy. Nothing is sent anywhere except the request to GitHub's public API for the issues.

Live: https://vanshajpoonia.github.io/already-filed/

Already Filed on a snapshot of ollama/ollama: open issues next to the earlier issues they resemble, with a button to copy Duplicate of

Why

Big repos get the same bug reported again and again. In zed-industries/zed, maintainers have linked 1,653 issues to the issue they duplicate; the original was filed a median 1,343 issues (64 days) earlier. Nobody remembers that far back, so every duplicate costs a maintainer a search, or a contributor's time on an issue…

Static files, no build step, no backend. MIT.

How I Built It

How Already Filed works: GitHub's API sends the issues to the browser tab, which cleans them, embeds them with EmbeddingGemma, scores every pair with a mix of the body vector, the title vector and keyword search, and shows the best matches for a person to decide

Ground truth that maintainers already made

The best thing about this problem is that the answers already exist. When a maintainer writes β€œDuplicate of #123”, or uses GitHub's close-as-duplicate menu, GitHub records a MarkedAsDuplicateEvent linking the two issues. So I downloaded every issue of three busy repos through the GraphQL API, with those links, and froze them into the repo:

Repo Issues Linked duplicates
ollama/ollama (tuning) 11,478 681
zed-industries/zed (test) 23,450 1,653
neovim/neovim (test) 14,762 379

The test replays each repo in the order issues were filed. For every issue that was later linked as a duplicate, the question is simple: is the issue it duplicates among the top suggestions, using only what existed on the day it was filed? Every choice below was made on ollama, then frozen. I did not look at zed or neovim until the end.

First attempt: barely better than Ctrl+F

The obvious version is: embed every issue with EmbeddingGemma, compare each new issue with every earlier one, and show the closest. On ollama it put the right issue in the top three 42% of the time. Keyword search (BM25, roughly what GitHub's own search box does) managed 38%. Four points is not a reason to download a 197 MB model.

Three things fixed it, and none of them was a bigger model.

1. Search where duplicates actually point. I looked at the issues maintainers pointed to: 91% were still open when the duplicate was filed, and another 7% had been closed in the 30 days before. Old closed issues are almost never the answer, but there are thousands of them, all waiting to be a near miss. Comparing each new issue only with issues open at the time (or closed in the last month) took the top three from 42% to 49%.

2. Tell the model what the vectors are for. EmbeddingGemma takes a task prompt. I had started with "sentence similarity", which sounds exactly right for "are these two issues the same?". On the tuning repo's titles I tried five prompts: "sentence similarity" found the right issue in the top three 41% of the time, "clustering" 40%, no prompt 47%, the document prompt 48%, and the retrieval prompt, task: search result | query:, 51%. Same weights, one line changed: on the full issues it took the top three from 49% to 61%.

3. Three signals instead of one. Issue templates make unrelated issues look alike: every ollama issue starts with "What is the issue?", "OS", "GPU", "Ollama version". Instead of hard-coding anyone's template, the app treats any line that appears in more than 2% of a repo's issues as template, and drops it, along with links, images and all but the first four lines of each log. Then each issue gets two vectors (title and body, and the title alone, because the title is where people name the bug), and keyword search comes back as a small third signal for exact error strings and model names that an embedding blurs. 0.7 Γ— body + 0.3 Γ— title + 0.1 Γ— keywords took the top three to 65% and the top one from 29% to 46%.

Measured on two repos it never saw

Then I froze everything and ran the two test repos, which I had not looked at since downloading them.

zed: top 1 top 3 top 5 neovim: top 1 top 3 top 5
Keyword search (BM25) 25% 38% 43% 26% 39% 45%
EmbeddingGemma alone 44% 62% 69% 42% 59% 64%
bge-small (a sixth of the size), same recipe 45% 64% 72% 40% 56% 60%
EmbeddingGemma recipe (shipped) 45% 65% 72% 43% 58% 64%

On zed's 1,653 duplicates, the issue a maintainer pointed to is in the top three suggestions 65% of the time, against 38% for keyword search. Of the duplicates only one of the two methods gets, 518 are EmbeddingGemma's and 64 are keyword search's. On neovim's 379 it is 58% against 39%. One result I did not expect: on neovim, EmbeddingGemma alone was as good as the full mix (59% against 58% at top three). The weights were fixed on ollama, and I left them alone rather than tune on the test set.

One honest surprise: a model a sixth of the size is almost as good once the recipe is right. bge-small, with the same search window and the same mix, is within two points of EmbeddingGemma on ollama and zed, and two to four behind on neovim. EmbeddingGemma is ahead at top three on all three repos, so it ships; but if you take one thing from this post, take the recipe: where to look, the right prompt, and a pinch of keywords.

Not every false alarm is false

The thresholds were chosen on ollama: β€œlikely” is where 5% of issues that were never linked to anything would still get a suggestion. On zed, β€œlikely” shows the right earlier issue for 12% of duplicates and fires on 4% of the other issues. On paper those 4% are all false alarms. But maintainers do not link every duplicate: plenty get closed as β€œcompleted” with a comment, or just sit there.

So I read them. node scripts/audit.mjs zed-industries/zed 30 prints a fixed random sample of 30 of zed's β€œfalse alarms”. By my reading, 21 are the same problem (two even have the same title, word for word: β€œAllow light/dark icon theme preference”, filed twice on the same day), 9 are related (same feature, a different bug: two Copilot problems in the agent panel, two MCP transport hangs with different triggers), and none are unrelated. That is my judgement, not the maintainers', and every number above still counts all 30 as wrong.

Running it in a browser tab

EmbeddingGemma runs through transformers.js, 4-bit, on WebGPU, or on WASM where there is no GPU (with a build that keeps the token table unquantised, because the WASM runtime lacks the quantised lookup). The issues come from GitHub's REST API, following GitHub's own pagination links: page numbers stop working after page 10 on big repos, which I found out from a 422 in the middle of a test run. The demo snapshot stores 8-bit vectors (4 MB for 2,711 issues), made by the same script and model as the tests.

Why Does Open Innovation Matter?

It needs no permission from anyone. The usual way to get duplicate detection is to install a bot: a GitHub App or Action that gets access to the repo and, often, sends each new issue to a hosted model API. Already Filed is a web page. Public issues come from GitHub's public API straight to your browser, and the model is a file your browser downloads. Add a token and it works on a private repo too, and the private issues still never leave the tab.

The ground truth is open too. Every number in this post comes from thousands of β€œDuplicate of #” comments that maintainers wrote in public. That is a labelled dataset nobody had to pay for, and it is the reason I can tell you how often this is wrong.

The thresholds only mean something because the model cannot change under me. β€œLikely” is a number chosen on one repo's similarity scores. With a hosted embedding API, a quiet model update would shift every score and nobody would know the thresholds had stopped meaning anything. These weights are a file; the tests and the page use the same one.

Reading 38,000 issues cost nothing. The test embeds every issue in both test repos with two models, on a laptop. No quota, no bill, no key to rotate, so it is cheap to measure properly instead of guessing.

My Agent Session

I built this with Claude Code as a pair programmer, and did not save the session to DevRelay, so here is the next best thing: every number in this post can be re-run.

git clone https://github.com/VanshajPoonia/already-filed
cd already-filed && npm install && npm test

That replays both test repos (it embeds about 38,000 issues the first time, about two hours on an M4, cached after) and prints the table above. npm run tune shows every choice made on ollama, and node scripts/audit.mjs zed-industries/zed 30 prints the false alarms I read.

The Lazy Payoff

Every duplicate in that test set was a maintainer doing the remembering by hand. In zed alone that happened 1,653 times, each time for an issue filed a median of 1,343 issues (two months) earlier.

  • For 65% of them, the right issue is in Already Filed's top three. That is one click on "Copy β€œDuplicate of #…”" instead of a search through 2,300 open issues.
  • It finds the ones nobody linked. Of 30 confident suggestions for zed issues that were never marked as duplicates, 21 were the same problem anyway. Each of those is a conversation happening twice.
  • It is lazy for reporters too. Pasting a draft into "About to file an issue?" takes seconds, and for about two thirds of zed's past duplicates, the issue they repeated would have been among the three it shows.
  • On ollama today, the snapshot flags 51 of 2,585 open issues as probably filed before. Finding them by hand would mean comparing every open issue with every other one; the snapshot does it in about six seconds.

Prize Categories

Best Use of Gemma: EmbeddingGemma (300M, 4-bit) runs in the browser and reads every issue. Every suggestion comes from its vectors, and the test runs the same model on 49,690 issues across three repos.

πŸ“° Read the original article on Dev.to AI

Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes β€” full credit and traffic to the original publisher.