Skip to main content
For the complete documentation index for agents and LLMs, see llms.txt.

RAG Pipeline with Attachments

This is an example of a retrieval-augmented generation (RAG) pipeline that runs on your files in Haystack Platform. Use it when users should be able to attach files to a question and get a cited answer that draws on both the attached files and your indexed documents. It retrieves and ranks documents from your files, converts the attachments at query time, and passes everything to the LLM.


How the Pipeline Works​

Pipelines contain recipes for how to execute a query. This pipeline does the following:

  • The retriever (an OpenSearchHybridRetriever) selects the most similar documents from the document store, using its embedder.
  • The ranker reranks the documents, and the meta_field_grouping_ranker groups them by file.
  • The multi_file_converter converts files attached at query time into documents, and the attachments_joiner combines them with the ranked documents.
  • The llm answers the question based on the documents and cites them by number.

The pipeline takes these inputs: query (the question), filters (metadata filters for retrieval), and files (the files to attach at query time). It returns documents, the documents passed to the LLM, and messages, which contain the generated answer.

Pipeline YAML​

To use this pipeline, copy the YAML and follow the steps in Pipeline Examples.

Example of a pipeline
# haystack-pipeline
components:
retriever:
# Selects the most similar documents from the document store
type: haystack_integrations.components.retrievers.opensearch.open_search_hybrid_retriever.OpenSearchHybridRetriever
init_parameters:
document_store:
type: haystack_integrations.document_stores.opensearch.document_store.OpenSearchDocumentStore
init_parameters:
embedding_dim: 768
hosts:
index: Standard-Index-English-EU-Demo-Schengen
max_chunk_bytes: 104857600
return_embedding: false
method:
mappings:
settings:
index.knn: true
create_index: true
http_auth:
use_ssl:
verify_certs:
timeout:
top_k: 20 # The number of results to return
fuzziness: 0
embedder:
type: deepset_cloud_custom_nodes.embedders.nvidia.text_embedder.DeepsetNvidiaTextEmbedder
init_parameters:
normalize_embeddings: true
model: intfloat/e5-base-v2

ranker:
type: deepset_cloud_custom_nodes.rankers.nvidia.ranker.DeepsetNvidiaRanker
init_parameters:
model: intfloat/simlm-msmarco-reranker
top_k: 8

meta_field_grouping_ranker:
type: haystack.components.rankers.meta_field_grouping_ranker.MetaFieldGroupingRanker
init_parameters:
group_by: file_id
subgroup_by:
sort_docs_by: split_id

llm:
type: haystack.components.generators.chat.llm.LLM
init_parameters:
# You can swap this for any other model. Switch to the Builder view and choose another model from the list on the component card.
chat_generator:
type: haystack.components.generators.chat.openai_responses.OpenAIResponsesChatGenerator
init_parameters:
model: "gpt-5.4"
user_prompt: >-
{% message role="user" %}

You are a technical expert.

You answer questions truthfully based on provided documents.

Ignore typing errors in the question.

For each document check whether it is related to the question.

Only use documents that are related to the question to answer it.

Ignore documents that are not related to the question.

If the answer exists in several documents, summarize them.

Only answer based on the documents provided. Don't make things up.

Just output the structured, informative and precise answer and nothing
else.

If the documents can't answer the question, say so.

Always use references in the form [NUMBER OF DOCUMENT] when using
information from a document, e.g. [3] for Document [3] .

Never name the documents, only enter a number in square brackets as a
reference.

The reference must only refer to the number that comes in square
brackets after the document.

Otherwise, do not use brackets in your answer and reference ONLY the
number of the document without mentioning the word document.

These are the documents:

{%- if documents|length > 0 %}

{% for document in documents %}

Document [{{ loop.index }}] :

Name of Source File: {{ document.meta.file_name }}

{{ document.content }}

{% endfor %}

{%- else %}

No relevant documents found.

Respond with "Sorry, no matching documents were found, please adjust the
filters or try a different question."

{% endif %}

Question: {{ question }}

Answer:

{% endmessage %}
required_variables: "*"
system_prompt: ""

attachments_joiner:
type: haystack.components.joiners.document_joiner.DocumentJoiner
init_parameters:
join_mode: concatenate
weights:
top_k:
sort_by_score: false

multi_file_converter:
type: haystack.core.super_component.super_component.SuperComponent
init_parameters:
input_mapping:
sources:
- file_classifier.sources
is_pipeline_async: false
output_mapping:
tabular_joiner.documents: documents
pipeline:
components:
file_classifier:
type: haystack.components.routers.file_type_router.FileTypeRouter
init_parameters:
mime_types:
- text/plain
- application/pdf
- text/markdown
- text/html
- application/vnd.openxmlformats-officedocument.wordprocessingml.document
- application/vnd.openxmlformats-officedocument.presentationml.presentation
- application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
- text/csv

text_converter:
type: haystack.components.converters.txt.TextFileToDocument
init_parameters:
encoding: utf-8

pdf_converter:
type: haystack.components.converters.pdfminer.PDFMinerToDocument
init_parameters:
line_overlap: 0.5
char_margin: 2
line_margin: 0.5
word_margin: 0.1
boxes_flow: 0.5
detect_vertical: true
all_texts: false
store_full_path: false

markdown_converter:
type: haystack.components.converters.txt.TextFileToDocument
init_parameters:
encoding: utf-8

html_converter:
type: haystack.components.converters.html.HTMLToDocument
init_parameters:
extraction_kwargs:
output_format: markdown
target_language:
include_tables: true
include_links: true

docx_converter:
type: haystack.components.converters.docx.DOCXToDocument
init_parameters:
link_format: markdown

pptx_converter:
type: haystack.components.converters.pptx.PPTXToDocument
init_parameters: {}

xlsx_converter:
type: haystack.components.converters.xlsx.XLSXToDocument
init_parameters: {}

csv_converter:
type: haystack.components.converters.csv.CSVToDocument
init_parameters:
encoding: utf-8

splitter:
type: haystack.components.preprocessors.document_splitter.DocumentSplitter
init_parameters:
split_by: word
split_length: 250
split_overlap: 30
respect_sentence_boundary: true
language: en

tabular_joiner:
type: haystack.components.joiners.document_joiner.DocumentJoiner
init_parameters:
join_mode: concatenate
sort_by_score: false
connections:
- sender: file_classifier.text/plain
receiver: text_converter.sources
- sender: file_classifier.application/pdf
receiver: pdf_converter.sources
- sender: file_classifier.text/markdown
receiver: markdown_converter.sources
- sender: file_classifier.text/html
receiver: html_converter.sources
- sender: file_classifier.application/vnd.openxmlformats-officedocument.wordprocessingml.document
receiver: docx_converter.sources
- sender: file_classifier.application/vnd.openxmlformats-officedocument.presentationml.presentation
receiver: pptx_converter.sources
- sender: file_classifier.application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
receiver: xlsx_converter.sources
- sender: file_classifier.text/csv
receiver: csv_converter.sources
- sender: text_converter.documents
receiver: splitter.documents
- sender: pdf_converter.documents
receiver: splitter.documents
- sender: markdown_converter.documents
receiver: splitter.documents
- sender: html_converter.documents
receiver: splitter.documents
- sender: pptx_converter.documents
receiver: splitter.documents
- sender: docx_converter.documents
receiver: splitter.documents
- sender: xlsx_converter.documents
receiver: tabular_joiner.documents
- sender: csv_converter.documents
receiver: tabular_joiner.documents
- sender: splitter.documents
receiver: tabular_joiner.documents

connections:
- sender: retriever.documents
receiver: ranker.documents
- sender: ranker.documents
receiver: meta_field_grouping_ranker.documents
- sender: multi_file_converter.documents
receiver: attachments_joiner.documents
- sender: meta_field_grouping_ranker.documents
receiver: attachments_joiner.documents
- sender: attachments_joiner.documents
receiver: llm.documents

inputs:
query:
- retriever.query
- ranker.query
- llm.question
filters:
- retriever.filters_bm25
- retriever.filters_embedding
files:
- multi_file_converter.sources

outputs:
documents: attachments_joiner.documents
messages: llm.messages

max_runs_per_component: 100

metadata: {}