exists thresholds classify
the remaining cases as missing or partial. You end up with find(), which returns the
exists probability and one relevance score per line.

- Tag each line with an ID so TypeSafe can point to it.
- Use a
Choiceto rank those line IDs by how well they answer the query. Choice probabilities always add up to 1, so a line ranks first even when none answer the query. - In the same request, use a
Noulto check whether the document contains an answer at all.
Setup
Get a TypeSafe API key
Create a key in the TypeSafe console and export it:Install the dependencies
JsonCache replays the included API responses, so the steps below run without an API key
or any spend. To make the requests live instead, set TYPESAFE_API_KEY and delete
json_cache.json.
Create the script
Startsemantic_search.py with the imports and the client:
Step 1: tag every line with an ID
The test document is GitHub’s Terms of Service, split into 218 clauses, so every search result points to one quotable line. Add tosemantic_search.py:
splitlines() leaves a list of 218 strings.
Now prefix each line with a short ID and join the lines back into one document. The model
uses these IDs to point to its answer.
DOCUMENT now looks like this:
Step 2: ask where the answer is
AChoice returns a probability for every option. Use the line IDs as the options,
and “pick an option” becomes “point to a line.”
None because the document already contains the text for each
ID. The query goes in instructions; the state stays unchanged between searches.
A
Choice accepts up to 255 options, so this recipe searches documents of
up to 255 lines in one request. Past that, search in two passes: one Choice picks a window
of lines, and a second ranks the lines inside it. Step 3: check whether an answer exists
Choice probabilities always add up to 1, so some line ranks first even when the document doesn’t answer the question. The ranking alone can’t distinguish a real answer from the closest irrelevant line. So ask a second question, in the same request:Step 4: send both questions in one request
Thesystem_one method answers both questions in one pass. The state is sent once, so
adding the existence check requires only a small amount of extra output.

relevance list keeps one score per line, in document order.
Step 5: read the result
Two pieces of local code finish the job:verdict() turns the raw exists probability
into three states, with a middle one for partial answers, and show() renders relevance
as a bar chart so the ranking is readable in a terminal.
Step 6: run the search
Ask four questions: two with direct answers, one with no answer, and one with a partial answer.What the scores mean
The first two queries return direct answers and the source lines needed to verify them. The other two show why the existence check matters:- Arbitration: The ranking gives the closest line a score of 0.86, but
existsis only 0.14. The answer is not in the document. - Parental permission: The age rule ranks first, but it doesn’t answer whether parental permission changes the rule. The result is partially addressed.
exists score tells you whether the result
answers the question.
Try it on your own document
Open the tagged contract in the TypeSafe playground to edit the questions against the same text. To search your own, swap the URL infetch_document() — every other
line of the script works off LINES.
