Skip to main content

Build a document Q&A app with Generic RAG

Build an application that answers questions over a fixed set of documents, without writing code. You create an application of the Generic RAG type, describe its pipeline in properties, and upload the documents once. This guide is for app developers and administrators. It assumes your administrator has deployed DIAL Generic RAG.

Prerequisites​

  • The Generic RAG application type registered in DIAL Core. Ask your administrator for its ID. The upstream ID is https://dial.epam.com/application_type_schemas/generic-rag.
  • Access to two models in DIAL Core: an embeddings model, and an LLM that accepts images.
  • To use the API: the DIAL Core URL, an API key, and your bucket ID. See Create a Quick App through the API.

Step 1: Design the pipeline​

Write the application's properties. This configuration needs only PostgreSQL. It indexes text two ways, keeps page images for the answers, and lets requests filter by two metadata fields:

{
"metadata_schema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"category": {"type": "string", "enable_filtering": true},
"published_on": {"type": "string", "format": "date", "enable_filtering": true}
},
"additionalProperties": true
},
"parsers": [
{"type": "unstructured_parser"},
{"type": "page_extractor"}
],
"indexes": {
"keywords": {
"display_name": "Keyword search",
"indexer": {"type": "text_normalizer", "language": "english"}
},
"semantic": {
"display_name": "Semantic search",
"indexer": {"type": "text_embeddings", "deployment_name": "text-embedding-3-small"}
}
},
"retriever": {
"type": "classic",
"document_selector": {"type": "explicit"}
},
"generation": {
"type": "default",
"llm": {"deployment_name": "gpt-4.1-2025-04-14"}
}
}
  • Parsers. unstructured_parser extracts text from PDF, Markdown, and plain text. page_extractor keeps PDF pages as images.
  • Indexes. Both use the default pgvector storage. keywords is a full-text index, and semantic an embeddings index.
  • Retriever. classic passes up to 4 page images to the LLM with the text. The explicit selector lets each request filter by metadata.
  • Models. Replace the deployment names with models you have.

For every option, see Generic RAG channel configuration.

Step 2: Create the application​

Create the application in DIAL Admin or through the API.

In DIAL Admin. Open the Generic RAG Application Runner and create an application from it. Set the properties from Step 1 in the application's Parameters.

Through the API. Save the application with PUT /v1/applications/{bucket}/{application-path}:

curl -X PUT "https://<DIAL_HOST>/v1/applications/<BUCKET>/policy-docs" \
-H "Content-Type: application/json" \
-H "api-key: <DIAL_API_KEY>" \
-d @- <<'EOF'
{
"displayName": "Policy documents",
"description": "Answers questions about company policies.",
"applicationTypeSchemaId": "https://dial.epam.com/application_type_schemas/generic-rag",
"applicationProperties": <PROPERTIES_FROM_STEP_1>
}
EOF

The application's ID is applications/<BUCKET>/policy-docs. DIAL Core validates the properties against the type's schema and rejects invalid ones.

Step 3: Upload the documents​

In DIAL Admin. When your administrator has deployed the frontend, the application's Parameters tab shows its documents. Select Add, choose a file, and fill in the metadata.

Through the API. Upload each file to the channel API:

curl -X POST "https://<DIAL_HOST>/v1/deployments/applications/<BUCKET>/policy-docs/route/channel/documents" \
-H "Api-Key: <DIAL_API_KEY>" \
-F "attachment=@travel-policy.pdf;type=application/pdf" \
-F 'metadata={"category": "travel", "published_on": "2026-01-15"}'

A document is searchable when its status is ready. Check it with GET .../route/channel/documents. When indexing runs in the background, the upload returns with created.

Step 4: Ask questions​

Select the application in DIAL Chat and ask a question. Answers cite the documents, with the page for a PDF, and link to them.

Through the API, a request can narrow the search with custom_fields.configuration:

curl -X POST "https://<DIAL_HOST>/openai/deployments/applications/<BUCKET>/policy-docs/chat/completions" \
-H "Content-Type: application/json" \
-H "api-key: <DIAL_API_KEY>" \
-d '{
"messages": [{"role": "user", "content": "How many days ahead must travel be booked?"}],
"custom_fields": {
"configuration": {
"retriever": {
"document_selector": {"type": "explicit", "filters": [{"category": "travel"}]}
}
}
}
}'

Generic RAG answers each message on its own, without the earlier messages of the conversation.

Step 5: Connect the MCP tools​

The application is also an MCP server, with tools to list, read, search, and cite the documents. To give them to a Quick App, add a dial-app Toolset:

{
"tool_sets": [
{
"type": "dial-app",
"name": "policies",
"deployment_id": "applications/<BUCKET>/policy-docs",
"transport": "mcp"
}
]
}

See Generic RAG MCP server for the tools, and dial-app for every field.

Result​

Users ask the application about the uploaded documents and get answers with citations. Agents use the same documents through MCP tools.

SymptomWhat to check
The upload fails with "unsupported file type"The parsers accept the file's MIME type.
A document stays createdA background job is queued. Ask your administrator about background jobs.
A document is ready but never citedGET .../route/channel/stats: a document with no text chunks had no text to extract.
The answer says it couldn't find the answerTurn on debug stages to see what each index returned. Ask your administrator for ENABLE_DEBUG_STAGES.

Further reading​