Skip to content

iterativeRag

Multi-pass RAG loop: retrieve → generate → if still unsatisfied, retrieve again.

Useful when a single retrieval isn't enough and the model needs to issue follow-up searches with a refined query. The current pass number is available as (shared as any).__ragIter (0-based) so retrieve can adapt its strategy.

Import

typescript
import { iterativeRag } from "flowneer/presets/rag";

Usage

typescript
interface RagState {
  question: string;
  context: string[];
  answer: string;
  followUpQuery?: string;
}

const flow = iterativeRag<RagState>({
  retrieve: async (s) => {
    const query =
      (s as any).__ragIter === 0 ? s.question : (s.followUpQuery ?? s.question);
    s.context = await vectorSearch(query);
  },
  generate: async (s) => {
    const result = await llm(buildPrompt(s));
    s.answer = result.answer;
    s.followUpQuery = result.followUpQuery; // set when more info is needed
  },
  needsMoreInfo: (s) => Boolean(s.followUpQuery),
  maxIterations: 3,
});

await flow.run({
  question: "Explain Flowneer presets",
  context: [],
  answer: "",
});

Options

OptionTypeDefaultDescription
retrieveNodeFn<S, P>Fetches documents; (shared as any).__ragIter (0-based) indicates the current pass
generateNodeFn<S, P>Generates a (potentially partial) answer; can signal more info is needed
needsMoreInfo(shared, params) => boolean | Promise<boolean>Return true to trigger another retrieve → generate pass
maxIterationsnumber3Maximum passes before the loop exits regardless

How It Works

initialize(__ragIter = 0, __ragDone = false)
loop(while !__ragDone && __ragIter < maxIterations):
  retrieve
  generate
  check needsMoreInfo → set __ragDone or increment __ragIter
cleanup(__ragIter, __ragDone)

Return value

Returns a FlowBuilder<S, P> — composable with all Flowneer plugins:

typescript
const flow = iterativeRag({ retrieve, generate, needsMoreInfo })
  .withCostTracker()
  .withTiming();

See Also