Returned by gr_read() and, with three extra fields, by answer_document().
Fields
answerCharacter(1). Always a single string. The sentinel
"NOT_IN_DOCUMENT"means the model reported the document does not contain the answer. Test it withis_not_found()-style matching rather than substring search.premisePresent only when the read spec checked the question's premise (
premise = TRUEingr_read_spec()).NAwhen the model reported nothing in the document contradicting the question; otherwise the sentence in which it said what the document states instead, which is thenansweras well, sois_not_found()isFALSE. It is the model's verdict, not a check harnessr made. Absent (NULL) for a spec that did not ask, and forscreenandextract, which answer no question.partialLogical(1).
TRUEwhen anything degraded: a call failed, chunks were dropped, a cap was hit, a strategy fell back, text was cut to fit, or pages of the document never became text (a scan read without OCR). Check this before trusting an answer.notesList. Why it is partial, and per-reader detail:
dropped_chunks,failed_calls,error,merge_levels,degraded_to_bm25,stop_reason,call_cap_reached,cost_cap_reached,summaries_truncated, and so on. Three can be set for every reader:cited_unknown, chunk ids the answer cited that were never sent;unverified_evidence, the number of quoted spans that are not in the chunk they claim to come from; andunread_pages, the pages that never became text. Any of them makes the answerpartial.warningsCharacter. What harnessr warned about while the document was ingested, cut and read, named by the warning's class. The warnings still print as they happen; this copy stays with the answer, including when the document came from the ingestion cache and nothing was raised again.
evidenceData frame or
NULL, with columnschunk_id,text,page,section,score,kind. Whattextholds depends on the reader: verbatim chunk text forstuff,retrieve,rerankanditerative; model-extracted passages forskim; per-chunk model answers formap_reduce.refineandhierarchicalreturnNULL.pageis populated only for PDF sources;scoreonly forretrieve(cosine) andrerank(0-10, model-judged). Where the evidence is model-written (skim), three more columns appear:source_text, the chunk the span claims to quote, plusverifiedandmatchfrom checking one against the other; seegr_verify_evidence(). Readers whose evidence is verbatim chunk text do not carry them, because the span and its source are the same string.kindsays what that row holds ("verbatim","extracted"or"answer") per row, because anensemblemixes them. A blank roxygen line inside a\describe{}item ends the item, which is why this is one paragraph.chunks_usedInteger vector of
chunk_ids that CONTRIBUTED to the answer. For the per-chunk readers this is a subset of the chunks sent: a chunk that answeredNOT_IN_DOCUMENTwas read and paid for but is not listed.notes$chunksreports how many were sent.reader,signatureWhich strategy ran, and its traversal signature (see
gr_reader_signature()).questionThe question, as asked.
traceThe gr_trace for this run. From
answer_document()it holds the whole run: ingestion, segmentation and the read. An answer taken from agr_compare()holds only its own recipe's segmentation and read (its segmentation requests, whichsemantic,propositionandcontextualwithcontext_source = "llm"bill, the pre-flight check and the reader's requests), because each recipe is counted apart. Ingestion and the other recipes are in the comparison's own trace,cmp$trace: cost or save that one as the record of what the comparison did. A trace passed in withtrace =is shared, not copied: this field is that trace itself, which still holds every run recorded into it, those before this one and those after it.trace_stepssays which of its steps are this run's.trace_stepsInteger
c(first, last): the steps oftracethis run made, orNULLwhen no trace was kept.as_json(),print()and the audit report (gr_audit_report()) use only these, so an answer read with a trace shared across runs does not carry other runs' prompts, calls or cost.recipe,document,segmentationAdded by
answer_document()andgr_compare(): the recipe name, the source and ingestion stats, and the chunk statistics the reader saw.
Methods
print() shows the answer, this run's calls, tokens and cost, where the
evidence came from, and, when the answer is partial, why. When the model
reported that the document contradicts the question's premise, it says so
above the answer, as the model's report. as_json()
serialises the answer (and premise, when it was checked) together with
every prompt and response this run made
(the steps of its trace that trace_steps names; for an answer from
gr_compare(), its recipe's read alone; see trace above).
See also
answer_document() and gr_read() which return one, gr_compare()
to compare several, is_not_found() to test the sentinel, as_json(),
new_answer() to build one in a custom reader
gr_read(), answer_document(), as_json()
Other reading functions:
gr_check_reader(),
gr_read(),
gr_read_spec(),
gr_reader_signature(),
gr_readers(),
gr_register_reader(),
is_not_found(),
new_answer()
Examples
cl <- gr_mock_client(function(m, p) "Revenue was 45.2 million dollars.")
ans <- answer_document(gr_example(), "What was revenue?", "fast", client = cl)
#> Using cached ingestion for this document + settings.
#> Segmenting with 'paragraph' (cap 4000 tokens, overlap 0).
#> Reading with 'stuff' (all|1|none) over 1 chunk(s).
ans$partial
#> [1] FALSE
ans$evidence[, c("chunk_id", "page", "score")]
#> chunk_id page score
#> 1 1 NA NA