Open-source adapters
Retrieval
The retrieval adapters make the decisions in a search-and-answer pipeline, one step at a time: which source to search, whether a passage answers the question, whether the passages provide enough evidence, which passage answers the question best, and whether the written answer is supported by its sources. The first part of this page follows one customer question to a home energy installer through each step: "How long is the warranty on an Aster 2 heat pump installed after March 2026?" The second part works with documents: what type a document is, which section a passage comes from, what kind of clause a contract provision is, and whether a value extracted from a document is right.
Each example below uses an input written for this page and shows the answer returned by the live API. To run one yourself, set JEFF_API_KEY as in the Quick start.
Choose where to search
Search source selection routes a query to one, several or none of the sources in a menu of document collections, databases and tools. You pass your sources as the labels:
Context
- menu
- - product_manuals: installation and user manuals for every heat pump and boiler the company sells - warranty_terms: the warranty terms for each product, by model and installation date - customer_orders: each customer's orders, installations and visits (a database) - pricing: current prices and offers
Input
How long is the warranty on an Aster 2 heat pump installed after March 2026?
Labels (the options)
- product_manuals
- Installation and user manuals for every heat pump and boiler the company sells
- warranty_terms
- The warranty terms for each product, by model and installation date
- customer_orders
- Each customer's orders, installations and visits (a database)
- pricing
- Current prices and offers
- none
- No source on the menu holds what the query needs, or no lookup is needed
- several
- The answer needs facts from two or more of these sources
- Answer (JSON)
- value warranty_terms, confidence 0.981
- Top options
- warranty_terms 0.981
- product_manuals 0.009
- customer_orders 0.005
import os import jeff with jeff.Jeff.remote("https://api.jeffhub.ai", token=os.environ["JEFF_API_KEY"], timeout_s=30) as client: decide = client.function("jeff.retrieval.query-route.source", context={ "menu": "- product_manuals: installation and user manuals for every heat pump and boiler the company sells\n- warranty_terms: the warranty terms for each product, by model and installation date\n- customer_orders: each customer's orders, installations and visits (a database)\n- pricing: current prices and offers", }, labels={ "product_manuals": "Installation and user manuals for every heat pump and boiler the company sells", "warranty_terms": "The warranty terms for each product, by model and installation date", "customer_orders": "Each customer's orders, installations and visits (a database)", "pricing": "Current prices and offers", "none": "No source on the menu holds what the query needs, or no lookup is needed", "several": "The answer needs facts from two or more of these sources", }) decision = decide("How long is the warranty on an Aster 2 heat pump installed after March 2026?") print(decision.value, decision.confidence)
warranty_terms is the source to search. Had the query needed no lookup, or more than one source, none or
several would say so.
Check that a passage answers the question
Passage relevance checks, for search and retrieval, whether a passage answers a question for the right subject and period: yes, partly or no. Here the search returned a passage about the older model:
Context
- source
- warranty_terms: the warranty terms for each heat pump and boiler a home energy installer sells
- question
- How long is the warranty on an Aster 2 heat pump installed after March 2026?
Input
Aster 1 heat pumps carry a five-year parts and labour warranty from the date of installation, provided the unit is serviced every year by an approved engineer.
- Answer (JSON)
- value no, confidence 0.993
- Top options
- no 0.993
- yes 0.006
- partly 0.001
import os import jeff with jeff.Jeff.remote("https://api.jeffhub.ai", token=os.environ["JEFF_API_KEY"], timeout_s=30) as client: decide = client.function("jeff.retrieval.passage-relevant.relevant", context={ "source": "warranty_terms: the warranty terms for each heat pump and boiler a home energy installer sells", "question": "How long is the warranty on an Aster 2 heat pump installed after March 2026?", }) decision = decide("Aster 1 heat pumps carry a five-year parts and labour warranty from the date of installation, provided the unit is serviced every year by an approved engineer.") print(decision.value, decision.confidence)
no means the passage does not answer the question: it is about the Aster 1, not the Aster 2. Exclude it from the material used to
write the answer.
Check that the passages are enough
Evidence sufficiency check checks, for search and retrieval, whether a set of passages is enough to answer a question: sufficient, insufficient or conflicting. Here are three passages the search found:
Context
- question
- How long is the warranty on an Aster 2 heat pump installed on or after 1 March 2026?
Input
- Aster 1 heat pumps carry a five-year parts and labour warranty from the date of installation, provided the unit is serviced every year by an approved engineer. - For Aster 2 units installed on or after 1 March 2026 the warranty is extended to seven years, parts and labour, with the same annual service condition. - Our boilers come with a two-year warranty as standard.
- Answer (JSON)
- value sufficient, confidence 0.991
- Top options
- sufficient 0.991
- conflicting 0.006
- insufficient 0.004
import os import jeff with jeff.Jeff.remote("https://api.jeffhub.ai", token=os.environ["JEFF_API_KEY"], timeout_s=30) as client: decide = client.function("jeff.retrieval.evidence-sufficient.sufficient", context={ "question": "How long is the warranty on an Aster 2 heat pump installed on or after 1 March 2026?", }) decision = decide([ "Aster 1 heat pumps carry a five-year parts and labour warranty from the date of installation, provided the unit is serviced every year by an approved engineer.", "For Aster 2 units installed on or after 1 March 2026 the warranty is extended to seven years, parts and labour, with the same annual service condition.", "Our boilers come with a two-year warranty as standard.", ]) print(decision.value, decision.confidence)
sufficient means the passages contain the answer (the second one does), so there is no need to search further.
conflicting would mean they disagree, and insufficient that more searching is needed.
Pick the passage that answers it
Passage selection and answer verification picks the passage that answers a question, and checks whether an answer is supported by its sources. Those are two functions. The first picks the passage, from the passages you pass as labels:
Input
How long is the warranty on an Aster 2 heat pump installed after March 2026?
Labels (the options)
- p1
- Aster 1 heat pumps carry a five-year parts and labour warranty from the date of installation.
- p2
- For Aster 2 units installed on or after 1 March 2026 the warranty is extended to seven years, parts and labour.
- p3
- Our boilers come with a two-year warranty as standard.
- none
- None of the passages answers the question.
- Answer (JSON)
- value p2, confidence 0.999
- Top options
- p2 0.999
- none 0
- p3 0
import os import jeff with jeff.Jeff.remote("https://api.jeffhub.ai", token=os.environ["JEFF_API_KEY"], timeout_s=30) as client: decide = client.function("jeff.retrieval.ground.rerank", labels={ "p1": "Aster 1 heat pumps carry a five-year parts and labour warranty from the date of installation.", "p2": "For Aster 2 units installed on or after 1 March 2026 the warranty is extended to seven years, parts and labour.", "p3": "Our boilers come with a two-year warranty as standard.", "none": "None of the passages answers the question.", }) decision = decide("How long is the warranty on an Aster 2 heat pump installed after March 2026?") print(decision.value, decision.confidence)
p2 is the key of the passage that answers the question. If none of them did, none would say so.
Check that the answer is supported
The second function of the same adapter checks the answer the pipeline wrote against its sources:
Context
- sources
- - Passage 1: Aster 1 heat pumps carry a five-year parts and labour warranty from the date of installation. - Passage 2: For Aster 2 units installed on or after 1 March 2026 the warranty is extended to seven years, parts and labour, provided the unit is serviced every year by an approved engineer.
Input
An Aster 2 installed after March 2026 has a seven-year parts and labour warranty, as long as it is serviced every year by an approved engineer.
- Answer (JSON)
- value supported, confidence 0.996
- Top options
- supported 0.996
- partly_supported 0.003
- contradicted 0.001
import os import jeff with jeff.Jeff.remote("https://api.jeffhub.ai", token=os.environ["JEFF_API_KEY"], timeout_s=30) as client: decide = client.function("jeff.retrieval.ground.grounding", context={ "sources": [ "Passage 1: Aster 1 heat pumps carry a five-year parts and labour warranty from the date of installation.", "Passage 2: For Aster 2 units installed on or after 1 March 2026 the warranty is extended to seven years, parts and labour, provided the unit is serviced every year by an approved engineer.", ], }) decision = decide("An Aster 2 installed after March 2026 has a seven-year parts and labour warranty, as long as it is serviced every year by an approved engineer.") print(decision.value, decision.confidence)
supported means everything the answer says is in the sources, including the yearly service condition, so it can
be shown to the customer.
Document classification
Document classification sorts a document into one of the types on your list (each with a description), or other. Here a supplier's document arrives in an installer's shared inbox:
Context
- sorting_desk
- The shared inbox of a home energy installer's office, where suppliers, customers and partners send documents.
Input
QUOTATION Q-2291 To: Fenwick Home Energy, 12 Quay Street For the supply of 40 outdoor mounting brackets (model MB-6) at 32.00 each: 1,280.00 plus VAT. This quotation is valid for 30 days. An invoice will follow on delivery.
Labels (the options)
- invoice
- A bill for goods or services already supplied, asking for payment
- quote
- An offer of a price for goods or services, before any order
- purchase_order
- The buyer's order to a supplier, placing an order at agreed prices
- delivery_note
- A note listing goods delivered, signed on receipt
- other
- None of these types
- Answer (JSON)
- value quote, confidence 0.997
- Top options
- quote 0.997
- other 0.002
- purchase_order 0
import os import jeff with jeff.Jeff.remote("https://api.jeffhub.ai", token=os.environ["JEFF_API_KEY"], timeout_s=30) as client: decide = client.function("jeff.retrieval.doc-type.doc_type", context={ "sorting_desk": "The shared inbox of a home energy installer's office, where suppliers, customers and partners send documents.", }, labels={ "invoice": "A bill for goods or services already supplied, asking for payment", "quote": "An offer of a price for goods or services, before any order", "purchase_order": "The buyer's order to a supplier, placing an order at agreed prices", "delivery_note": "A note listing goods delivered, signed on receipt", "other": "None of these types", }) decision = decide("QUOTATION Q-2291\nTo: Fenwick Home Energy, 12 Quay Street\nFor the supply of 40 outdoor mounting brackets (model MB-6) at 32.00 each: 1,280.00 plus VAT.\nThis quotation is valid for 30 days. An invoice will follow on delivery.") print(decision.value, decision.confidence)
quote means the document offers a price before any order; the mention of an invoice to follow does not make it
one.
Document section classification
Document section classification identifies the section of a document that a passage comes from, using a list of section types and descriptions, or returns none. Here is a passage from an installation services agreement:
Context
- document
- An installation services agreement between a home energy installer and a housing developer.
Input
Either party may end this agreement on 60 days' written notice. If the developer ends it, any invoices then unpaid fall due at once.
Labels (the options)
- scope
- What work the installer will do, and where
- payment
- Prices, invoicing and when payment is due
- termination
- How and when either party may end the agreement
- liability
- Who is responsible for loss or damage, and the limits
- none
- None of these sections
- Answer (JSON)
- value termination, confidence 1
- Top options
- termination 1
- payment 0
- none 0
import os import jeff with jeff.Jeff.remote("https://api.jeffhub.ai", token=os.environ["JEFF_API_KEY"], timeout_s=30) as client: decide = client.function("jeff.retrieval.section-id.section", context={ "document": "An installation services agreement between a home energy installer and a housing developer.", }, labels={ "scope": "What work the installer will do, and where", "payment": "Prices, invoicing and when payment is due", "termination": "How and when either party may end the agreement", "liability": "Who is responsible for loss or damage, and the limits", "none": "None of these sections", }) decision = decide("Either party may end this agreement on 60 days' written notice. If the developer ends it, any invoices then unpaid fall due at once.") print(decision.value, decision.confidence)
termination is the section: the passage is about ending the agreement, even though it also mentions unpaid
invoices.
Contract clause classification
Contract clause classification labels a single contract provision with its clause type, such as governing law, notices or confidentiality. The clause types are the function's own, so there are no labels to pass:
Context
- document
- A commercial contract filed with the U.S. Securities and Exchange Commission (SEC)
Input
This Agreement and any dispute arising out of or in connection with it shall be governed by and construed in accordance with the laws of the State of Delaware, without regard to its conflict of laws principles.
- Answer (JSON)
- value governing_laws, confidence 0.93
- Top options
- governing_laws 0.93
- applicable_laws 0.055
- qualifications 0.001
import os import jeff with jeff.Jeff.remote("https://api.jeffhub.ai", token=os.environ["JEFF_API_KEY"], timeout_s=30) as client: decide = client.function("jeff.legal.legal-clauses.clause_type", context={ "document": "A commercial contract filed with the U.S. Securities and Exchange Commission (SEC)", }) decision = decide("This Agreement and any dispute arising out of or in connection with it shall be governed by and construed in accordance with the laws of the State of Delaware, without regard to its conflict of laws principles.") print(decision.value, decision.confidence)
governing_laws is the clause type: the provision names the law that governs the contract.
Extracted value validation
Extracted value validation checks a value extracted from a document (a field and its value) and says whether it is correct, the wrong value, the wrong field, not in the document, or ambiguous. Here an extraction step read the invoice's total as 420.00:
Context
- document
- INVOICE 7781 Issued: 14 October 2026 Due: 13 November 2026 Fenwick Home Energy, 12 Quay Street Aster 2 heat pump, supplied and installed: 8,400.00 VAT (5%): 420.00 Total due: 8,820.00
Input
field: total value: 420.00
- Answer (JSON)
- value wrong_field, confidence 0.991
- Top options
- wrong_field 0.991
- ambiguous 0.003
- correct 0.003
import os import jeff with jeff.Jeff.remote("https://api.jeffhub.ai", token=os.environ["JEFF_API_KEY"], timeout_s=30) as client: decide = client.function("jeff.retrieval.extract-check.check", context={ "document": "INVOICE 7781\nIssued: 14 October 2026 Due: 13 November 2026\nFenwick Home Energy, 12 Quay Street\nAster 2 heat pump, supplied and installed: 8,400.00\nVAT (5%): 420.00\nTotal due: 8,820.00", }) decision = decide({ "field": "total", "value": "420.00", }) print(decision.value, decision.confidence)
wrong_field means the value is in the document but belongs to another field: 420.00 is the VAT, not the total.
Extract the field again before storing a value.