Axis 3 is a registry, so how the model is made to read a chunk set is
yours to define. A registered reader is a first-class one: it appears in
gr_readers(), can be named in a gr_recipe() or an ensemble, and is
subject to the same call and spending limits as the built-ins.
Arguments
- name
Reader name. Re-registering an existing name replaces it.
"auto"is reserved foranswer_document().- fn
Function of
(chunks, question, client, spec, trace)returning agr_answer. See the section below.- signature
Traversal signature,
"select|calls|state". Two readers with the same signature are the same methodology under two names;gr_compare()uses it, together with the ingest and segment specs, to decide whether two recipes are the same experiment, andensemblerefuses members that share one. Aselectof"all"says the reader sends every chunk, so a run whose chunks alone would cost more thanmax_cost_usdis refused before its first request.- description
One-line description, shown by
gr_readers().- cost_calls
Human-readable call count in terms of N chunks (
"N + 1","1 + embeddings"), shown bygr_readers().
Writing a reader
Your function receives:
chunksA gr_chunks.
chunks$chunksis the data frame:chunk_id,text,tokens,chars,page,section,block_id.questionThe question, already validated as non-blank.
clientPass it to
gr_call(); never construct your own.specA
gr_read_spec(). Honour at leastmodel,max_answer_tokensandtemperature.tracePass it to every
gr_call()so your calls are counted and priced, and checkreadgpt:::trace_can_call(trace)before each one so the run's call and spending limits are respected.
Return new_answer(). Budget your prompt with gr_budget() rather than
assuming the document fits.
See also
new_answer() to build the return value, gr_readers(),
gr_reader_signature(), gr_read(), gr_answer, gr_budget()
Other reading functions:
gr_answer,
gr_read(),
gr_read_spec(),
gr_reader_signature(),
gr_readers(),
is_not_found(),
new_answer()
Examples
# A reader that answers from the single longest chunk.
gr_register_reader("longest", signature = "one|1|none", cost_calls = "1",
description = "answer from the longest chunk only",
fn = function(chunks, question, client, spec, trace) {
d <- chunks$chunks
i <- which.max(d$tokens)
res <- gr_call(client, list(
list(role = "user", content = paste0(d$text[i], "\n\nQuestion: ", question))),
model = spec$model, trace = trace, label = "longest.answer")
new_answer(res$text, "longest", question, d$chunk_id[i], trace)
})
ch <- gr_segment(readgpt_example(), list(method = "sentence", max_tokens = 120))
#> Using cached ingestion for this document + settings.
#> Segmenting with 'sentence' (cap 120 tokens, overlap 0).
gr_read(ch, "What was revenue?", gr_mock_client(function(m, p) "45.2 million"),
"longest")$answer
#> Reading with 'longest' (one|1|none) over 6 chunk(s).
#> [1] "45.2 million"