Skip to content

Streaming the trace ​

ask_stream is a generator: it yields an Event for each step as it happens, and its return value is the final Answer.

python
gen = rag.ask_stream("Who founded the university where the author of Harbor Light studied?")
while True:
    try:
        event = next(gen)
    except StopIteration as stop:
        answer = stop.value
        break
    print(f"{event.kind:9} {event.text}")

print(answer.text, answer.sources)

rag.ask(question) does exactly this and returns the answer; answer.trace keeps every event.

Event kinds ​

KindWhentext
planthe run startsthe question
rankthe agent ran RANKthe query
readthe agent ran READthe passage name
searchthe agent ran SEARCH (only when enabled)the query
thoughtthe agent answered early, or wrote an invalid actiona short note
hopa sub-question was resolvedsub-question → answer
backfillthe backfill was addedhow many passages
verifythe compose call startshow many passages are composed
answerthe compose call returnedthe answer

The classic agent adds its own kinds (fuzzy, list, toc, peek, semantic).

Each Event has kind, text, step (the forager turn, where there is one) and detail, and event.to_dict() gives a JSON-ready view.

In a web app ​

python
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
import json

app = FastAPI()
rag = RagX("./docs")

@app.get("/ask")
def ask(q: str):
    def events():
        gen = rag.ask_stream(q)
        while True:
            try:
                yield json.dumps(next(gen).to_dict()) + "\n"
            except StopIteration as stop:
                yield json.dumps({"kind": "final", **stop.value.to_dict()}) + "\n"
                return
    return StreamingResponse(events(), media_type="application/x-ndjson")

Released under the Apache 2.0 License.