Par Anthropic Citations
2025.gada 23.janvārī uzņēmums Anthropic papildināja Anthropic API funkcionalitāti ar Citations — iespēju Claude 3.5 Sonnet un Claude 3.5 Haiku modeļiem citēt atgrieztā rezultāta tekstu, tādējādi dodot iespēju lietotājam pārliecināties par modeļa atbildes pareizību.
“Citēšana” nozīmē to, ka modelis API atbildei pievienos papildu informāciju: no kura teksta daļas vai lapas (.pdf gadījumā) ir sagatavota atbilde, norādot citējamo tekstu (cited_text) un citus metadatus — no kura dokumenta nāk citāts (document_index un document_title) un kura tieši teksta daļa ir iekļauta citējamā tekstā (start_char_index, end_char_index vai start_page_number un end_page_number .pdf failu gadījumā).
Šī brīža risinājums nav multimodāls: tas strādā tikai ar tekstu, tātad, ja pievienotajā .pdf failā būs attēli, tad informāciju no šiem attēliem Claude modeļi citēt nemācēs.
Kā izmantot jauno funkcionalitāti?
Vispirms uzinstalē anthropic Python pakotni:
pip install anthropic
Tad Python rīkā ieimportē šo bibliotēku un izveido client instanci. Tev būs nepieciešama API atslēga — pamācība kā to izveidot ir pieejama šeit. Piemērā es izmantoju arī keyring pakotni API atslēgas pārvaldībai, taču API atslēgu vari glabāt arī vides mainīgajos (environment variables) vai .env
failā:
import anthropic
import keyring # pip install keyring
client = anthropic.Anthropic(
api_key=keyring.get_password('Claude_API_key', 'Medium_API_test'),
)
Tad nodefinē Claude modeli, kādu izmantosi API pieprasījumā (priekš citēšanas šobrīd der tikai Claude 3.5 Sonnet vai Claude 3.5 Haiku).
# https://docs.anthropic.com/en/docs/about-claude/models
MODEL = "claude-3-5-sonnet-20241022" # or claude-3-5-haiku-20241022
Atkarībā no teksta veida (text/plain, application/pdf vai content), kāds tiek padots modelim, mainās messages
saturs client.messages.create
metodei. Šajā piemērā izmantoju .pdf failam nepieciešamo struktūru, bet zemāk norādītajā piemērā parādīti arī pārējie veidi.
import base64
import httpx # pip install httpx
# pdf fails (no interneta)
pdf_url = "https://www.lza.lv/images/Zinatnes-vestnesis/2024/ZV_12_2024.pdf"
pdf_data = base64.standard_b64encode(httpx.get(pdf_url).content).decode("utf-8")
# lietotāja uzvedne
user_prompt = "Kādi raksti (nosauc raksta nosaukumu un autoru) ir iekļauti pēdējā izdevumā 'Zinātnes vēstnesis'?"
# API izsaukums
response = client.messages.create(
model=MODEL,
max_tokens=1024,
messages=[
{
"role": "user",
"content": [
{
"type": "document",
"source": {
"type": "base64",
"media_type": "application/pdf",
"data": pdf_data
},
"title": "Zinātnes Vēstnesis", # optional
"context": "Latvijas Zinātņu akadēmijas, Latvijas Zinātnes padomes un Latvijas Zinātnieku savienības laikraksts, Nr.11 (649)", # optional
"citations": {"enabled": True}
},
{
"type": "text",
"text": user_prompt
}
]
}
]
)
Kā redzams, lai citēšana API risinājumā strādātu message
laukā ir jānodefinē "citations”: {“enabled”: True}
. title
un context
vērtības nav obligātas, taču tas noder pie rezultātu atspoguļošanas, ja gala rezultātā ir jāparāda avota nosaukums (title
).
Atbildes apstrāde .pdf gadījumā varētu būt šāda:
from IPython.display import Markdown, display # pip install ipython
text = '' # modeļa atbilde
citation_num = 1
citations = '' # citētais teksts
# Ne visiem response.content elementiem ir atribūts "citations"
# tāpēc ar if tiek veikta papildu apstrāde, lai parādītu citēšanas rezultātu
# tajos gadījumos, kad elementam ir šāds atribūts.
for i in response.content:
if hasattr(i, 'citations'):
citation_nums = []
for citation in i.citations:
citation_nums.append(citation_num)
pages = f"({citation['start_page_number']}.lpp.)" if citation['start_page_number'] == citation['end_page_number']-1 else f"({citation['start_page_number']}.-{citation['end_page_number']}.lpp.)"
citations = citations + f'[{citation_num}] "{citation['document_title']}" - {citation['cited_text']} {pages}\n\n'
citation_num += 1
text = text + i.text + ' ['+','.join(str(item) for item in citation_nums)+']'
else:
text += i.text
display(Markdown((text+'\n\n**Avoti:**\n\n'+citations if citations.strip() else text)))
Claude modeļa atbilde var sastāvēt no viena vai vairākiem response.content
saraksta elementiem. Katrs elements ir TextBlock
klase, kurā var būt tikai teksts (i.text
) vai teksts kopā ar citēšanas atribūtu (i.citations
) — tāpēc iepriekšējā piemērā izmantots if hasattr(i, ‘citations’)
nosacījums, kurš apstrādā citēšanas datus tikai tad, ja tādi klasē ir nodefinēti.
Apvienojot modeļa tekstu (i.text
) ar citēšanas tekstu (citation[‘cited_text’]
) un papildu metadatiem (start_page_number, end_page_number un document_title), iepriekšējā koda rezultāts izskatās sekojoši:
Ņem vērā, ka “citēšanas” funkcionalitāte šobrīd ir iekļauta tikai API risinājumā. Ja to pašu jautājumu uzdosi claude.ai rīkā, tad iegūsi atbildi bez norādes kurā lapā šī informācija atrodas:
Tāpēc claude.ai rīka uzvednē jau pašā sākumā prasi, lai tas norāda lapaspuses numurus no kuriem modelis ir apkopojis atbildi.
Viss Python kods ar text/plain, application/pdf un content piemēriem ir pieejams šeit. Oficiālo Citations funkcionalitātes dokumentāciju atradīsi šeit.
Līdzīgi risinājumi citos rīkos: Grounding with Google Search.
Raksta sagatavošanā tika izmantota Python 3.12.4 versija un sekojošas pakotņu versijas:
- anthropic: 0.43.0
- httpx: 0.27.2
- ipython: 8.31.0
- keyring: 25.6.0