- Je bewaart de exacte bronversie en posities bij geselecteerde passages.
- Je controleert verwijzingsgeldigheid apart van ondersteuning van een claim.
Probeer ook echte tekstvectoren in het embedding-lab.
Een bronlabel achter een zin ziet overtuigend uit. Toch kan het naar een andere versie wijzen, een verkeerd stukje tekst citeren of niets over de claim zeggen. We controleren die vragen afzonderlijk.
De vorige les koos een passage. Nu bewaren we haar identiteit, vullen we een begrensde context en meten we verwijzingen. Inhoudelijke ondersteuning komt in deze oefening uit een handmatig vastgelegde supporttabel.
1. Tel de verpakking mee
Een context is meer dan losse brontekst. We geven ieder opgenomen blok een label, document-ID, versieprefix en halfopen tekeninterval. De volledige versiehash blijft daarnaast in de citaatmetadata staan.
Met twee korte bronnen kunnen we ieder teken narekenen. De bron “Een lamp.” heeft negen Python-codepunten; de header en newline maken het eerste blok 35 tekens. Het tweede blok is 38 tekens.
records = [
dict(id='a', title='Lamp',
text='Een lamp.'),
dict(id='b', title='Sensor',
text='Een sensor.')
]
docs = document_snapshots(records)
chunks = [word_chunks(d)[0]
for d in docs]
full = pack_context(chunks, docs, 1000)
print(full['text'])
print(full['used_chars'])
# [S1] a@154351ed61a0 [0,9)
# Een lamp.
#
# [S2] b@e5ec903db522 [0,11)
# Een sensor.
# 75
Tussen blokken staan twee newlines: 35+2+38=75. Bij budget 74 past het eerste blok, maar het tweede niet. Een vergeten separator laat het programma ongemerkt over zijn eigen limiet gaan.
Identieke tekst nemen we eenmaal op, ook als twee document-IDs dezelfde tekst bevatten. Alleen opgenomen blokken krijgen een volgend S-label. Een niet-passende passage wordt overgeslagen; een latere, kleinere passage mag nog passen.
small = pack_context(chunks, docs, 74)
print(small['used_chars'])
base = dict(title='T', text='Een lamp.')
copies = document_snapshots(
[dict(base, id=i)
for i in ['a', 'b']])
same = [word_chunks(d)[0]
for d in copies]
one = pack_context(same, copies, 1000)
print(len(one['citations']))
# 35
# 1
Schrijf pack_context met de gegeven snapshot- en chunkhelpers. Valideer alle chunks vooraf, ook degene die later niet passen. Verander de exacte bronuitsneden niet.
Dit greedy beleid zoekt geen optimale combinatie. Overlappende maar verschillende teksten blijven aparte blokken. Ons budget telt codepunten; een echt model vraagt een tokenbudget voor instructies, vraag, bronnen én antwoordreserve.
012. Controleer identiteit vóór inhoud
Een verwijzing kan structureel geldig zijn en toch nergens passen. verify_citations controleert eerst documentbestaan, daarna de volledige versiehash, dan het interval en ten slotte de exacte substring.
Een oude versie krijgt dus stale-source, ook als haar posities óók ongeldig zijn. Zo blijft duidelijk welke controle eerst mislukte. Structurele fouten, zoals een dubbel bronlabel of een boolean als positie, geven ValueError.
c = full['citations'][0]
alterations = [
{},
dict(document_id='unknown'),
dict(revision='0'*64, start=-1),
dict(start=-1),
dict(quote='Andere woorden.')
]
for edits in alterations:
result = verify_citations(
[{**c, **edits}], docs)
print(result[0]['status'])
# valid
# unknown-source
# stale-source
# invalid-span
# quote-mismatch
Schrijf de controle in deze volgorde. Zoek niet opnieuw naar vergelijkbare tekst en normaliseer geen witruimte: daarmee zou je een verkeerde verwijzing verbergen. De offsets zijn Python-stringposities, geen UTF-8-byteposities.
Verander één onderdeel en volg de technische controle. Ondersteuning is voor deze voorbeelden afzonderlijk met de hand beoordeeld.
Reset duurt tien seconden. De lamp brandt groen.
Verwijzing S1
Document: lamp
Bronversie: 14a0cc3959ad
Tekeninterval: [0, 26)
Reset duurt tien seconden.
Technische controles
- Document bestaatgoed
- Volledige versie kloptgoed
- Tekeninterval is geldiggoed
- Exacte substring kloptgoed
Te controleren claimReset duurt tien seconden.
Een hash controleert de vastgelegde tekstversie, niet de waarheid of betrouwbaarheid van de bron. De inhoud wordt nooit als opdracht uitgevoerd.
3. Scheid geldige verwijzingen van bewijs
Stel dat drie claims samen drie verwijzingen plaatsen. S1 en S2 zijn technisch geldig; S9 is niet vastgelegd. Alleen S1 ondersteunt in onze handlabels de claim dat er een lamp is.
De resetclaim citeert S2, maar “Een sensor.” geeft geen resetinstructie. De kleurclaim citeert niets. Technische geldigheid, passend bewijs en claimdekking krijgen daarom verschillende tellers.
Noem T het totale aantal verwijzingen, V het aantal geldige en S het aantal geldige ondersteunende verwijzingen. N is het aantal claims en G het aantal claims met minstens één passende geldige verwijzing.
Hier zijn T=3, V=2, S=1, N=3 en G=1. Dat geeft reference_validity R=2/3, support_precision P=1/3 en claim_coverage C=1/3.
claims = [
dict(id='lamp', refs=['S1', 'S9']),
dict(id='reset', refs=['S2']),
dict(id='kleur', refs=[])
]
support = {'lamp': ['S1'], 'reset': []}
scores = citation_scores(
claims, ['S1', 'S2'], support)
for value in scores.values():
print(round(value, 3))
empty = citation_scores([], [], {})
print(list(empty.values()))
# 0.667
# 0.333
# 0.333
# [None, None, None]
Schrijf citation_scores met de afzonderlijke noemers. Een onbekende of ongeldige verwijzing kan nooit ondersteuning tellen, ook als de supporttabel haar noemt. Bij een nulnoemer geeft de betreffende ratio None.
Onze handlabels nemen aan dat één passende bron voldoende is. Tegenstrijdige bronnen of claims die meerdere bewijsstukken vereisen, vragen een rijker protocol. Een hash bewijst bovendien geen betrouwbare afzender of waarheid.
03Wat neem je mee?
- Contextbudgetten bevatten ook headers, scheidingstekens en exacte brontekst.
- Een geldig citaat is technisch terugvindbaar; inhoudelijke ondersteuning is een aparte beoordeling.
- Verwijzingsratio’s tellen links, claimdekking telt claims.
Hierna meten we retrieval en antwoorden samen, met zichtbaar verschillende foutcategorieën.