> ## Documentation Index
> Fetch the complete documentation index at: https://docs.flexorch.com/llms.txt
> Use this file to discover all available pages before exploring further.

# LangChain Integration

> Use FlexOrchRetriever to wire FlexOrch semantic search into any LangChain chain.

<Note>
  This guide covers the **platform SDK** (`flexorch-sdk`). For local file auditing with the zero-dependency OSS library, see [flexorch-audit LangChain](/open-source/langchain).
</Note>

## Install

```bash theme={null}
pip install flexorch-sdk langchain langchain-openai
```

***

## FlexOrchRetriever

`FlexOrchRetriever` implements LangChain's `BaseRetriever` interface. It calls `POST /v1/search` under the hood and returns `RAGDocument` objects that are duck-type compatible with LangChain's `Document`.

```python theme={null}
from flexorch_sdk import FlexOrch, FlexOrchRetriever

client = FlexOrch()  # reads FLEXORCH_API_KEY from env

retriever = FlexOrchRetriever(
    client,
    quality_threshold="B",   # include A and B grade chunks
    pii_masked=True,          # only return PII-safe chunks
    top_k=5,
    mode="hybrid",            # auto | semantic | hybrid | structured
    document_type="invoice",  # optional filter
    language="tr",            # optional ISO 639-1 filter
)

docs = retriever.invoke("invoices over 10000 EUR")

for doc in docs:
    print(doc.page_content[:100])
    print(doc.metadata)
```

### Parameters

| Parameter           | Type           | Default  | Description                                             |
| ------------------- | -------------- | -------- | ------------------------------------------------------- |
| `client`            | `FlexOrch`     | required | Authenticated SDK client                                |
| `quality_threshold` | `str`          | `"B"`    | Minimum grade — `"A"`, `"B"`, `"C"`, or `"D"`           |
| `pii_masked`        | `bool \| None` | `None`   | Filter to PII-masked chunks only                        |
| `top_k`             | `int`          | `5`      | Number of results to return                             |
| `mode`              | `str`          | `"auto"` | Search mode: `auto`, `semantic`, `hybrid`, `structured` |
| `document_type`     | `str \| None`  | `None`   | Filter by document type                                 |
| `language`          | `str \| None`  | `None`   | Filter by ISO 639-1 language code                       |

<Note>
  `mode="semantic"` and `mode="hybrid"` require a **Pro or Enterprise** plan. Pass `mode="auto"` to fall back to structured search on lower plans.
</Note>

***

## RetrievalQA chain

```python theme={null}
from flexorch_sdk import FlexOrch, FlexOrchRetriever
from langchain.chains import RetrievalQA
from langchain_openai import ChatOpenAI

client = FlexOrch()
retriever = FlexOrchRetriever(client, quality_threshold="B", mode="hybrid")

qa = RetrievalQA.from_chain_type(
    llm=ChatOpenAI(model="gpt-4o-mini"),
    retriever=retriever,
    return_source_documents=True,
)

result = qa.invoke("What is the payment term on invoice FTR-2024-001?")
print(result["result"])

for doc in result["source_documents"]:
    print(doc.metadata["quality_grade"], doc.page_content[:60])
```

***

## LCEL chain

```python theme={null}
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
from langchain_openai import ChatOpenAI

prompt = ChatPromptTemplate.from_template(
    "Answer the question based only on the context below.\n\n"
    "Context: {context}\n\nQuestion: {question}"
)

def format_docs(docs):
    return "\n\n".join(doc.page_content for doc in docs)

chain = (
    {"context": retriever | format_docs, "question": RunnablePassthrough()}
    | prompt
    | ChatOpenAI(model="gpt-4o-mini")
    | StrOutputParser()
)

print(chain.invoke("Total amount on the March invoices?"))
```

***

## Quality and language filters

```python theme={null}
# German contracts — grade A only
retriever_de = FlexOrchRetriever(
    client,
    quality_threshold="A",
    document_type="sales_proposal",
    language="de",
    top_k=10,
)

# Turkish payroll — grade B+, PII masked
retriever_tr = FlexOrchRetriever(
    client,
    quality_threshold="B",
    pii_masked=True,
    document_type="payroll",
    language="tr",
)
```

***

## Async support

`FlexOrchRetriever` implements `aget_relevant_documents()` for async chains:

```python theme={null}
docs = await retriever.aget_relevant_documents("payment terms")
```

***

## RAGDocument fields

`FlexOrchRetriever.invoke()` returns a list of `RAGDocument` objects:

| Field          | Type   | Description                                      |
| -------------- | ------ | ------------------------------------------------ |
| `page_content` | `str`  | Chunk text (LangChain compatible)                |
| `text`         | `str`  | Alias for `page_content` (LlamaIndex compatible) |
| `metadata`     | `dict` | Chunk metadata                                   |

Metadata keys:

| Key             | Description                           |
| --------------- | ------------------------------------- |
| `chunk_id`      | Unique chunk identifier               |
| `dataset_id`    | Source dataset                        |
| `quality_grade` | `A` \| `B` \| `C` \| `D`              |
| `quality_score` | 0.0 – 1.0                             |
| `doc_type`      | Document classification               |
| `language`      | ISO 639-1 language code               |
| `pii_masked`    | `true` if PII was masked              |
| `score`         | Retrieval relevance score (0.0 – 1.0) |

<CardGroup cols={2}>
  <Card title="RAG pipeline overview" icon="route" href="/guides/rag-pipeline">
    End-to-end guide: export vs. managed search
  </Card>

  <Card title="LlamaIndex integration" icon="link" href="/guides/llamaindex">
    FlexOrchReader for VectorStoreIndex
  </Card>
</CardGroup>
