Run this notebook in Google Colab
Every step below as an executable notebook, with the overview playing inline. Nothing to install.
How It Works
Five endpoints, each doing one job:
The retrieval here is deliberately plain: vectors in a Python list, cosine similarity in a loop. That is the right amount of machinery for a few dozen sources and it keeps the moving parts visible. When you outgrow it, Building a Private RAG Bot covers the same pipeline with a real vector database and a re-ranking pass.
Setting Up
One dependency, and a key from the API settings page.notebook.py and start with the imports and configuration. The two lists at the bottom are the whole state of the notebook: sources records what you added, and chunks holds the searchable pieces.
HOSTS maps a host name to a voice. Both voices come from tts-xai-v1, and that matters: voices belong to models, and sending a voice from one family to a model from another is the most common first mistake with the speech endpoint.
Choosing a Model That Will Not Go Stale
Hardcoding a chat model into a project guarantees the project ages. Venice publishes which model currently holds each role through/models/traits, so you can ask for the current default instead of naming one.
most_intelligent buys you a stronger model for the reasoning-heavy summarization, and default_reasoning gives you one that thinks in the open. See Models for the full list.
Adding Sources
A source is either a URL or a file on disk, and Venice has an endpoint for each. Both return plain text, which is the point: the rest of the notebook does not care where a source came from./augment/scrape returns Markdown rather than raw HTML, so there is no boilerplate stripping to write. /augment/text-parser accepts PDF, Word, Excel, and plain text up to 25 MB, and reports a token count alongside the text. Document Processing covers its options in full.
Chunking and Embedding
Embedding a whole document produces one vector that is an average of everything it says, which is too blunt to retrieve a specific claim. Splitting it produces vectors that each mean something. Split on paragraph boundaries rather than a fixed character count. A chunk that stops mid-sentence retrieves badly, because the embedding is of a fragment.embed batches because the endpoint takes a list, and one request for sixty-four chunks is far cheaper in wall time than sixty-four requests. text-embedding-bge-m3 returns 1024 dimensions and handles multilingual sources well.
Adding a source is now read, split, embed, and record. The magnitude of each vector gets stored alongside it, because it never changes and recomputing it inside the similarity loop is wasted work.
number is what makes citation possible later. Every chunk remembers which source it came from, so an answer can point back at it.
Retrieving the Right Passages
Cosine similarity between the question vector and every chunk vector, sorted, top k. For a few thousand chunks this runs faster than the network call that produced the question vector.Answering with Citations
The difference between a grounded answer and a confident guess is entirely in the prompt. Two instructions do the work: answer only from the notes, and say so when the notes fall short. Without the second one a model will quietly fill the gap from memory, which is the failure mode you are trying to design out. Numbering the notes in the prompt gives the model a citation vocabulary. It writes[2], and you can resolve that back to a source.
Writing the Overview Script
Here is where the notebook stops being a search box. A summary is something you read; an overview is something you listen to, and the two want different prose. Dialogue works better in audio because the turn-taking does the pacing for you, and a question from one host is a natural way to introduce the next idea. Three constraints matter, and all three come from the audio rather than the text:- No markdown, no URLs. A speech model reads
https://docs.venice.aione character at a time. - Spell out abbreviations. T E E the first time, not tee.
- Vary turn length. Evenly sized turns sound like two people reading a list at each other.
enum on speaker means every turn maps to a voice you have.
spread samples chunks across the whole collection instead of retrieving by similarity. Taking every nth chunk is crude and works well: it reaches the end of long documents, which taking the first twelve never would.
Treat the turn count as a hint rather than an instruction. Asking for sixteen has produced anywhere from sixteen to twenty-eight here, depending on how much the sources have to say. If you need a hard ceiling, truncate turns before rendering rather than arguing with the prompt.
Rendering Two Voices into One Track
Each turn becomes one speech request, with the voice chosen by who is speaking.pool.map preserves input order, so the turns come back in the order they were written no matter which finishes first. Four workers is a deliberate ceiling rather than a maximum: more concurrency will start returning 429s on lower tiers, and the job is already dominated by the longest single turn.
Running It
Making It Yours
The sources are the whole game. Everything downstream is bounded by what you put in. Scraped pages bring their navigation and footers along, which is harmless for answering but shows up in an overview as a host earnestly discussing a documentation index. If that happens, drop chunks below a length threshold or filter obvious furniture before embedding. Swap the voices.HOSTS is two entries in a dictionary. tts-xai-v1 ships twenty-six voices, and other families have their own; GET /models?type=tts lists voices per model. Two voices that contrast clearly are easier to follow than two that are merely different.
Clone your own. Voice Cloning turns a short sample into a voice handle you can drop straight into HOSTS.
Add a third participant. Nothing in the pipeline assumes two speakers except the schema enum. Adding an interviewer who only asks questions changes the feel considerably.
Keep the script. Writing turns to a JSON file next to the audio costs two lines and saves a re-render every time you want to tweak one sentence.
Where to Go Next
Private RAG Bot
The same retrieval pipeline with a real vector database and re-ranking.
Cited Answers with Web Search
Find the sources automatically instead of naming them yourself.
Text-to-Speech
Reference for the speech endpoint, its voices, and streaming.
Document Processing
Everything the text parser accepts, and what it returns.