New to Telerik Document ProcessingStart a free 30-day trial

Custom PartialContextQuestionProcessor

Updated on Feb 19, 2026

This article explains how to create a custom PartialContextQuestionProcessor configuration by supplying your own IContextRetriever and related interface implementations. You can tailor every step: splitting text, producing embeddings, ranking relevance, enforcing token limits, formatting context, and retrieving it efficiently to optimize performance, cost, accuracy, or compliance.

When you need full control over fragmentation, embedding, similarity ranking, and retrieval, use the constructor that accepts an IContextRetriever:

csharp
PartialContextQuestionProcessor(
    IChatClient chatClient,
    IContextRetriever contextRetriever,
    IEmbeddingSettings settings,
    SimpleTextDocument document)

This constructor gives you end‑to‑end control over how document text is fragmented, embedded, stored, and later selected (ranked) as context for a question, forming your custom PartialContextQuestionProcessor pipeline.

Interfaces

All extension points live in Telerik.Documents.AI.Core (as abstractions) with their default implementations in Telerik.Documents.AI.RAG:

InterfaceResponsibilityUsed By
IContextFragmentsManagerSplits raw document text into token-bounded semantic fragments (pages, sections, paragraphs)Fragmentation stage
IEmbedderConverts fragments into embeddings/vectors for similarity comparisonEmbedding stage
ISimilarityCalculatorScores fragment relevance against a question/promptRanking stage
ITokensCounterCounts tokens for limits enforcement (fragment size, total context)Throughout pipeline
IEmbeddingSettingsProvides token & size limits + formatting hintsConfiguration source
IContextRetrieverOrchestrates loading text, preparing embeddings, and returning best contextRetrieval stage
ISupportJsonEmbeddings / ISupportPlainTextEmbeddingsControl how context is formatted for the model (JSON vs plain text)Formatting stage
IFragments / IFragmentData structures representing chunk collections and individual chunksShared across stages

Life Cycle

  1. SetContextAsync(text, embeddingTokenSize) - Text is fragmented (IContextFragmentsManager), tokens checked (ITokensCounter), embeddings generated (IEmbedder), and stored.
  2. Question time (GetContextAsync(question)) - Similarity scores computed (ISimilarityCalculator), top fragments selected within limits, context formatted (plain or JSON).
  3. Processor sends formatted context + question via IChatClient and returns model answer.

Custom Implementation

The example below constructs a custom PartialContextQuestionProcessor by supplying a DefaultContextRetriever that mixes user implementations (custom IContextFragmentsManager and IEmbedder) with default components (DefaultSimilarityCalculator, DefaultTokensCounter, and the retriever's own orchestration). This hybrid approach lets you optimize the most impactful stages (fragmentation + embedding) without rewriting the entire retrieval pipeline.

DefaultEmbedder is only available on net8-windows and higher. On other target frameworks you must supply your own IEmbedder (as shown below with CustomOpenAIEmbedder).

c#
// Load the DOCX document
string filePath = @"path\to\your\document.docx";
DocxFormatProvider formatProvider = new DocxFormatProvider();
RadFlowDocument flowDocument;

using (FileStream fs = File.OpenRead(filePath))
{
    flowDocument = formatProvider.Import(fs, TimeSpan.FromSeconds(10));
}

// Convert the document to a simple text representation
SimpleTextDocument plainDoc = flowDocument.ToSimpleTextDocument(TimeSpan.FromSeconds(10));

// Set up the AI client (Azure OpenAI in this example)
string key = "AZUREOPENAI_KEY";
string endpoint = "AZUREOPENAI_ENDPOINT";
string model = "gpt-4o-mini";

Azure.AI.OpenAI.AzureOpenAIClient azureClient = new AzureOpenAIClient(
    new Uri(endpoint),
    new Azure.AzureKeyCredential(key),
    new Azure.AI.OpenAI.AzureOpenAIClientOptions());
ChatClient chatClient = azureClient.GetChatClient(model);

IChatClient iChatClient = (IChatClient)chatClient;
int maxTokenCount = 128000;
int maxNumberOfEmbeddingsSent = 20;
int embeddingTokenSize = 500;

IEmbeddingSettings settings = EmbeddingSettingsFactory.CreateSettingsForSpreadDocuments(maxTokenCount, produceJsonFormattedContext: false);
IContextFragmentsManager customContextFragmentsManager = new CustomOpenAIContextFragmentsManager(new DefaultTokensCounter(settings)); // Implemented by the user
IEmbedder customEmbedder = new CustomOpenAIEmbedder();
DefaultContextRetriever defaultContextRetriever = new DefaultContextRetriever(
    customContextFragmentsManager,
    customEmbedder,
    new DefaultSimilarityCalculator(customEmbedder),
    new DefaultTokensCounter(settings),
    settings);

using (PartialContextQuestionProcessor partialContextQuestionProcessor =
    new PartialContextQuestionProcessor(
        iChatClient,
        defaultContextRetriever,
        settings,
        plainDoc))
{
    string question = "What is the main topic of the document?";
    string answer = await partialContextQuestionProcessor.AnswerQuestion(question);
    Console.WriteLine("Answer: " + answer);
}

See Also