Flux
Sign in
Integrations

LlamaIndex

Answer questions from your own PDFs using only the passages that matter, and give your LlamaIndex agent live web search.

2 min read · Updated 14 Sept 2026
On this page

A query over a long PDF sends every page to your model, even when the answer is one paragraph. You pay for all of it, and the answer is harder to find.

Lineage cuts each page down to the passages that answer the question before your model sees them. The names and dates in those passages stay attached.

Set up

Shell
pip install llama-index-core llama-index-llms-openai llama-index-readers-file requestsexport FLUX_API_KEY="<your key>"export OPENAI_API_KEY="<your key>"

Lineage

Answer from your PDF

Load the PDF and add FluxLineage as a node postprocessor. Each page is cut to the passages that answer the question before your model, passed in with llm, sees it.

handbook.py
import osimport requestsFLUX = "https://fluxsearch.io/api/v1"HEADERS = {"Authorization": f"Bearer {os.environ['FLUX_API_KEY']}"}from llama_index.core import SimpleDirectoryReader, SummaryIndexfrom llama_index.core.postprocessor.types import BaseNodePostprocessorfrom llama_index.core.schema import NodeWithScore, TextNodefrom llama_index.llms.openai import OpenAIclass FluxLineage(BaseNodePostprocessor):    def _postprocess_nodes(self, nodes, query_bundle=None):        if query_bundle is None:            return nodes        kept = []        for node in nodes:            response = requests.post(                f"{FLUX}/lineage",                headers=HEADERS,                json={"text": node.node.get_content(), "query": query_bundle.query_str},                timeout=120,            )            response.raise_for_status()            for passage in response.json()["results"]:                text = TextNode(text=passage["enriched_text"], metadata=node.node.metadata)                kept.append(NodeWithScore(node=text, score=passage["score"]))        return kepthandbook = SimpleDirectoryReader(input_files=["employee-handbook.pdf"]).load_data()index = SummaryIndex.from_documents(handbook)query_engine = index.as_query_engine(    llm=OpenAI(model="gpt-5-mini"),    node_postprocessors=[FluxLineage()],)response = query_engine.query("How many days of annual leave do new starters get?")before = sum(len(page.text) for page in handbook)after = sum(len(node.get_content()) for node in response.source_nodes)print(f"{before:,} characters in the handbook, {after:,} sent to the model")print(response)
Output
1,038 characters in the handbook, 87 sent to the modelNew starters receive 25 days of annual leave per year, plus UK bank holidays.

A plain function is a tool. Your model calls Flux for anything current.

agent.py
import asyncioimport osimport requestsFLUX = "https://fluxsearch.io/api/v1"HEADERS = {"Authorization": f"Bearer {os.environ['FLUX_API_KEY']}"}from llama_index.core.agent.workflow import FunctionAgentfrom llama_index.llms.openai import OpenAIdef web_search(query: str) -> str:    """Search the live web. Returns passages with provenance and their source URLs."""    response = requests.post(        f"{FLUX}/search",        headers=HEADERS,        json={"query": query, "max_results": 5, "enrich": 3},        timeout=120,    )    response.raise_for_status()    passages = [        f"{passage['enriched_text']} ({result['url']})"        for result in response.json()["results"]        for passage in (result["lineage"] or {}).get("results", [])    ]    return "\n\n".join(passages) or "No passages found."agent = FunctionAgent(tools=[web_search], llm=OpenAI(model="gpt-5-mini"))async def main():    print(await agent.run("When are the remaining UK bank holidays this year?"))asyncio.run(main())
Output
Assuming you mean from today (14 Sep 2026), the remaining UK bank holidays in 2026 are:- Monday 30 November - St Andrew’s Day (Scotland only)- Friday 25 December - Christmas Day (England & Wales, Scotland, Northern Ireland)- Monday 28 December - Boxing Day (substitute day for 26 Dec, observed in England & Wales, Scotland, Northern Ireland)If you want the list for a particular nation only (e.g. England & Wales, Scotland or Northern Ireland) or to include local/one‑off holidays, tell me which and I’ll tailor it.

Call Flux as an LLM

For sourced passages on one question with no agent, use OpenAILike with function calling off.

llm.py
import osfrom llama_index.llms.openai_like import OpenAILikeflux = OpenAILike(    model="flux-search-1",    api_base="https://fluxsearch.io/api/v1",    api_key=os.environ["FLUX_API_KEY"],    is_chat_model=True,    is_function_calling_model=False,)print(flux.complete("What is the latest on the Mars Sample Return mission?"))
Output
This mission plan was officially cancelled in April 2011.A key mission requirement for the Mars 2020Perseverance rover mission was that it help prepare for MSR.[39][40][41] The rover landed on 18 Feb…Its appearance has been noted to have similarities with a Lightsaber from the Star Wars movies.[42]Perseverance roverThe Mars 2020 mission landed the Perseverance rover in the Jezero crater in Februa…It has collected multiple samples and will continue to do so, packing them into cylinders for later return in the MSR Campaign. [what: It -> Perseverance]As of July2025,[update] 33 out of 43 sample tubes have been filled,[46] including 8 igneous rock samples, 13 sedimentary rock sample tubes, 3 Igneous/Impactite rock sample tubes, a Serpentinite rock…Further, 10 of the 43 tubes are left as backups at the Three Forks Sample Depot.[50]However, after a project review critical of its cost and complexity, NASA announced that the Mars Sample Return pro…NASA turned to industry and the Jet Propulsion Laboratory (JPL) to form a new, more fiscally feasible mission profile to retrieve the samples.[52][53]From 21 December 2022, Perseverance started a cam……

Next steps