Terug naar de blog

Je iPhone-foto’s blijven lokaal, en Comma vindt ze

Ook de modellen draaien lokaal. Vraag het in je eigen woorden, en Comma vindt de foto’s in een lokale index.

Aan de slagLees de documentatie

Je boekt online een huurauto en het formulier vraagt het nummer en de vervaldatum van je rijbewijs. Het rijbewijs ligt niet binnen handbereik. Je weet nog dat je er vorig jaar foto’s van hebt gemaakt, voor- en achterkant, toen je het nieuwe kreeg, maar die zitten ergens tussen tienduizenden foto’s op je iPhone. Je wilt het Comma in je eigen woorden vragen en die twee foto’s terugkrijgen.

Deze handleiding laat één manier zien om dat op te zetten: bouw met lokale modellen een index van je foto’s en laat Comma daarin zoeken. Het is een voorbeeldopstelling op één Mac, geen ingebouwde functie van Comma.

Je bibliotheek blijft lokaal

Comma heeft geen kopie van je foto’s nodig. Het zware werk, de tekst in elke afbeelding lezen en elke foto omzetten in vectoren, doen lokale modellen. Wat de agent krijgt, is het resultaat van een zoekopdracht: een paar foto-ID’s, hun datums, de tekst die erin is gevonden en, als je moet kiezen, één contactblad met miniaturen. Alleen de foto’s die je uiteindelijk kiest, gaan de chat in.

De foto’s zelf synchroniseren nog steeds via iCloud; ‘lokaal’ betekent hier de tekstherkenning, de vectoren en de index na de export. Gebruikt Comma een cloudmodel, dan gaan deze zoekresultaten, en elke afbeelding die je Comma laat bekijken, naar de modelaanbieder die je hebt gekozen. Bij een document als een rijbewijs bevat de herkende tekst het nummer en het adres. De index zelf wordt nergens heen gestuurd. Comma is open source, en je kunt het ook op je eigen machine draaien.

Bouw de foto-index

De index haakt in op de weg die je foto’s al afleggen. Op de iPhone verandert niets.

Foto’s synchroniseren via iCloud-foto’s van de iPhone naar de Mac en worden geëxporteerd; daarna maken lokale modellen miniaturen, lezen ze tekst, berekenen ze twee sets beeldvectoren en bouwen ze een volledige tekstindex 1 · Foto’s naar de Mac iPhone maakt foto’s zoals altijd iCloud-foto’s synchroniseert ze naar de Mac Foto’s op de Mac bibliotheek op een externe schijf Originelen exporteren bewaart tijd en plaats 2 · Verwerken met lokale modellen Miniaturen latere stappen lezen alleen deze Tekst Apple Vision Beeldvectoren Chinese-CLIP Beeldvectoren Qwen3-VL-Embedding Volledige tekstindex SQLite de zoekopdracht rangschikt met elke set en voegt beide ranglijsten samen Foto’s synchroniseren via iCloud-foto’s van de iPhone naar de Mac en worden geëxporteerd; daarna maken lokale modellen miniaturen, lezen ze tekst, berekenen ze twee sets beeldvectoren en bouwen ze een volledige tekstindex 1 · Foto’s naar de Mac iPhone maakt foto’s zoals altijd iCloud-foto’s synchroniseert ze naar de Mac Foto’s op de Mac bibliotheek op een externe schijf Originelen exporteren bewaart tijd en plaats 2 · Verwerken met lokale modellen Miniaturen latere stappen lezen alleen deze Tekst Apple Vision Beeldvectoren Chinese-CLIP Beeldvectoren Qwen3-VL-Embedding Volledige tekstindex SQLite de zoekopdracht rangschikt met elke set en voegt beide ranglijsten samen
Elke stap na de export draait op de Mac.

Het opzetten gaat in drie stappen:

  1. Haal de foto’s naar de Mac. Synchroniseer de foto’s van je iPhone met de Mac via iCloud-foto’s en exporteer nieuwe foto’s elke dag naar een map.

  2. Verwerk ze met lokale modellen. Herken de tekst in elke afbeelding en zet de afbeelding daarna om in vectoren met Chinese-CLIP en Qwen3-VL-Embedding.

  3. Sla ze op in een lokale index. Bewaar de resultaten in een lokale database, met één opdracht om erin te zoeken. In dit voorbeeld heet die opdracht lpa.

Wat een zoekopdracht oplevert

Lokaal is een zoekopdracht één opdracht. Eén aanroep kan meerdere formuleringen bevatten, en de modellen laden maar één keer. De agent maakt van woorden als ‘vorig jaar’ een datumbereik.

sh
lpa search "driver license" "driver's license" "驾照" \
  --from 2025-01-01 --to 2026-01-01 --prefer text --json -n 9

Elk resultaat laat zien wat voor bewijs erachter zit:

LabelBetekenis
TeksttrefferElk woord is gevonden in de tekst van de afbeelding.
MogelijkDe afbeelding lijkt erop. Dingen die op elkaar lijken, verwar je makkelijk.
Lage zekerheidAlleen getoond als er niets beters is.

--prefer text zet teksttreffers vooraan, handig voor documenten, kaarten en schermafbeeldingen. --prefer picture zet afbeeldingen die erop lijken vooraan, handig voor een kat of een strand. Bijna gelijke foto’s die binnen een paar minuten zijn gemaakt, nemen maar één plek in de lijst in; de rest hangt eronder.

Een Comma-chat: gevraagd naar het wifiwachtwoord van een pension aan zee, leest Comma de netwerknaam en het wachtwoord van een kaartje op een kamerfoto en stuurt de foto.
Een teksttreffer: de netwerknaam en het wachtwoord komen uit de woorden op het kaartje in de foto. De foto is voor dit voorbeeld gegenereerd.
Een Comma-chat: gevraagd om foto’s van een kat op de vensterbank, geeft Comma drie foto’s van de kat op een vensterbank terug.
Een beeldtreffer: nergens in deze foto’s staat ‘kat’ of ‘vensterbank’; de beeldvectoren vinden ze.

Als de bovenste resultaten onzeker zijn, gokt de agent niet. Hij zet de miniaturen van de kandidaten op één genummerd blad, hoogstens negen, en vraagt jou te kiezen.

Een genummerd contactblad van drie bij drie: 1 en 2 zijn de voor- en achterkant van een voorbeeldrijbewijs, 3 en 4 zijn wifikaartjes, en de rest zijn kandidaten met lage zekerheid.
Een voorbeeld van een contactblad; het rijbewijs is een voorbeeldkaart. 1 en 2 zijn teksttreffers voor de voor- en achterkant, 3 en 4 lijken op kaarten, en de rest zijn kandidaten met lage zekerheid. Antwoord ‘1 en 2’, en de agent stuurt beide kanten van het rijbewijs.

Hoe de twee sets vectoren samenwerken, is vastgesteld door te kalibreren op een volledige bibliotheek van ongeveer 50.000 foto’s. Met alleen Qwen3-VL-Embedding kwamen de juiste antwoorden die iemand had aangewezen lager uit dan met alleen Chinese-CLIP. Met de twee ranglijsten samengevoegd deed elk gecontroleerd item het minstens zo goed als met een van de twee modellen alleen. ‘Mogelijk’ wordt ook alleen gegeven als de gelijkenis van beide modellen boven de drempel komt: bij één testvraag daalde het aantal foto’s met ‘Mogelijk’ van 4.970 naar 4. De prijs is dat een zoekopdracht 3,5 tot 6 seconden duurt in plaats van ongeveer 3.

Dit voorbeeld draait op een MacBook Air met 16 GB geheugen, met de 2B-versie van Qwen3-VL-Embedding. Op een krachtigere machine kun je grotere Qwen-modellen gebruiken:

  • Een groter vectormodel. Vervang Qwen3-VL-Embedding-2B door Qwen3-VL-Embedding-8B. Na de wissel moeten de vectoren van alle foto’s opnieuw worden berekend met het nieuwe model.

  • Beschrijvingen en tags voor elke foto. Draai daarnaast Qwen3-VL-4B-Instruct of Qwen3-VL-8B-Instruct om voor elke foto een beschrijving van één regel en een paar tags te schrijven en die in de tekstindex op te slaan. Op een MacBook Pro met 24 GB geheugen draait het 8B-model bijvoorbeeld met 8-bits kwantisatie. De tags zijn goed voor een grove schifting; ze zijn niet gegarandeerd juist.

En Engels? Chinese-CLIP is vooral getraind op Chinese afbeeldingen en teksten, dus voor Engelse zoekvragen is het niet betrouwbaar. De andere twee onderdelen hebben er geen last van: de tekstherkenning leest zowel Chinees als Engels, en Qwen3-VL-Embedding ondersteunt veel talen. Zet daarom Chinese en Engelse formuleringen in dezelfde zoekopdracht, zoals de opdracht hierboven doet; dat kun je in een Skill vastleggen. Zijn je bibliotheek en je vragen vooral Engels, dan kun je Chinese-CLIP ook vervangen door de oorspronkelijke CLIP, wat opnieuw betekent dat de vectoren opnieuw moeten worden berekend.

Vind familie en vrienden

Foto’s groepeert de gezichten van dezelfde persoon al. De index gebruikt die groepen direct en doet zelf geen gezichtsherkenning.

  1. Benoem eerst de personen. De eerste keer kiest de agent een paar groepjes foto’s uit die groepen, nummert ze en vraagt je wie het zijn. Pas als je antwoordt ‘3 is mama’, onthoudt hij het. Een groep die je niet hebt bevestigd, geldt als niemand.

  2. Zoek op persoon. Daarna kijkt de zoekopdracht bij een naam alleen naar foto’s waar die persoon op staat. Namen tellen op: noem twee personen en je krijgt alleen foto’s met hen allebei, dus jullie foto’s samen.

  3. Combineer met andere voorwaarden. Een naam kan samengaan met wat er op de afbeelding staat en wanneer, zoals ‘foto’s van mama en mij op het strand vorig jaar’:

sh
lpa search "beach" --person Me --person Mom \
  --from 2025-01-01 --to 2026-01-01 --prefer picture --json -n 9

Is een naam niet bevestigd, of hebben twee personen dezelfde naam, dan zegt de zoekopdracht dat in plaats van te gokken. Een verkeerde naam kun je verbeteren, en elke verbetering kun je ongedaan maken.

Zo worden video’s gevonden

Video’s worden apart van foto’s doorzocht. Een standaardzoekopdracht kijkt alleen naar foto’s. Wil je bijvoorbeeld de video waarin je kind de verjaardagskaarsjes uitblaast, zeg dan tegen Comma dat je een video zoekt, en Comma voegt --source video aan de zoekopdracht toe:

sh
lpa search "blowing out candles" "birthday cake" --source video --json -n 9

Daarachter zitten drie stappen:

  1. Beelden nemen. De video zelf gaat nooit een model in. Het indexeerprogramma neemt elke 5 seconden een beeld, hoogstens 12 per video.

  2. Zoeken op beeld. De beelden doorlopen dezelfde verwerking als foto’s: tekstherkenning en beide sets vectoren. Een zoekopdracht vergelijkt deze beelden; zodra er één past, is de hele video gevonden, en die neemt maar één plek in de resultaten in.

  3. De video sturen. Als je hebt gekozen, stuurt de agent hem met lpa video.

Een Comma-chat: gevraagd om een video van bamboevlotten in Yangshuo, geeft Comma één video van 12 seconden terug van vlotten die over een stuwtje glijden.
Een videozoekopdracht: de beelden die passen horen bij één video, dus de video is één resultaat.

Voorlopig kijkt het alleen naar het beeld, niet naar het geluid. Wat er in een video wordt gezegd, is nog niet doorzoekbaar, en mensen in een video worden nog niet herkend. Het aantal beelden is begrensd, dus iets wat in een lange video even voorbijflitst, wordt misschien niet gevonden.

Zo is LocalPhotoAgent gebouwd

De lpa in deze handleiding komt uit LocalPhotoAgent, een indexeerprogramma dat we zelf hebben geschreven en dat we open source gaan maken. Het indexeren staat hierboven beschreven; nog twee punten:

  • Het kan op elk moment stoppen. Elke stap van elke foto wordt apart vastgelegd. Stopt het halverwege, dan gaat het de volgende keer verder; verander je een instelling, dan draait alleen de stap die het raakt opnieuw. Tijdens het werk houdt het geheugen, temperatuur en schijfruimte in de gaten en pauzeert het zodra een ervan over zijn grens gaat.

  • Het geeft de agent een paar opdrachten. lpa search zoekt, lpa sheet maakt een contactblad, lpa preview stuurt foto’s en lpa video stuurt video’s. Als de agent foto’s zoekt, roept hij ze in deze volgorde aan:

De Comma-agent voert via de Connector lpa search uit, bij twijfel lpa sheet, daarna lpa preview of lpa video; alleen het blad en het versturen lezen de externe schijf Comma-agent voert opdrachten uit via de Connector lpa search zoekt alleen in de database lpa sheet maakt bij twijfel een blad lpa preview / video stuurt de foto of de video Externe schijf miniaturen en originelen, alleen gelezen voor een blad of het versturen De Comma-agent voert via de Connector lpa search uit, bij twijfel lpa sheet, daarna lpa preview of lpa video; alleen het blad en het versturen lezen de externe schijf Comma-agent voert opdrachten uit via de Connector lpa search zoekt alleen in de database lpa sheet maakt bij twijfel een blad lpa preview / video stuurt de foto of de video Externe schijf miniaturen en originelen, alleen gelezen voor een blad of het versturen

Verbind Comma

Dit gaat ervan uit dat LocalPhotoAgent al werkt op je Mac. Verbinden gaat in vier stappen:

  1. Voeg een apparaat toe. Ga in Comma naar Settings > Devices en klik op Add device om een installatieopdracht te krijgen.

  2. Voer de opdracht uit. Voer hem uit in Terminal op de Mac met de bibliotheek, om de Comma Connector te installeren.

  3. Zet toegang aan. Een nieuw apparaat begint op Off. Zet het op Full, zodat de agent lpa kan uitvoeren.

  4. Schrijf een Skill. Zeg tegen de agent dat hij eerst zoekt, bij twijfel een contactblad stuurt en foto’s pas stuurt nadat jij hebt gekozen. Je kunt Comma ook gewoon vragen om ‘een Skill te maken’.

Daarna vraag je het gewoon zoals in elke chat: ‘Zoek de foto’s van mijn rijbewijs van vorig jaar, voor- en achterkant.’

Een Comma-chat: gevraagd om de foto’s van het rijbewijs van vorig jaar, voor- en achterkant, stuurt Comma twee foto’s van een voorbeeldrijbewijs.
De vraag uit het begin van deze handleiding, beantwoord. Het rijbewijs is een voorbeeldkaart.

Vertrouwen en grenzen

De index leest de originelen alleen. Hij verplaatst, bewerkt of verwijdert ze nooit. Een zoekopdracht raakt de externe schijf helemaal niet aan; alleen het maken van een contactblad en het sturen van een foto lezen ervan. Foto’s verplaatsen of verwijderen valt buiten deze opstelling. Let wel: met Full-toegang kan de agent op deze Mac ook andere opdrachten dan lpa uitvoeren.

Een teksttreffer betekent alleen dat de woorden zijn gevonden, niet dat het de foto is die je zoekt. ‘Mogelijk’ is alleen een kandidaat. Als Comma een verzoek als klaar markeert, controleer dan de foto’s die het heeft gestuurd.

De eerste keer kun je zeggen: ‘Zoek de foto’s van mijn rijbewijs van vorig jaar. Laat me eerst het contactblad zien, en stuur, verplaats of verwijder niets.’

Try Comma, Now.

Aan de slag