Skip to content

RAG Types

The Strategos.Rag package provides vector store adapters for Retrieval-Augmented Generation (RAG) patterns.

IVectorSearchAdapter

Interface for vector similarity search operations.

Methods

MethodParametersReturnsDescription
SearchAsyncstring query, int topK, double minRelevance, CancellationToken ctTask<IReadOnlyList<SearchResult>>Searches for similar documents
SearchAsyncfloat[] embedding, int topK, double minRelevance, CancellationToken ctTask<IReadOnlyList<SearchResult>>Searches with pre-computed embedding
UpsertAsyncDocument document, CancellationToken ctTaskInserts or updates document
DeleteAsyncstring documentId, CancellationToken ctTaskRemoves document from index

Example

csharp
public class RetrieveContextStep : IWorkflowStep<QueryState>
{
    private readonly IVectorSearchAdapter _vectorSearch;

    public RetrieveContextStep(IVectorSearchAdapter vectorSearch)
    {
        _vectorSearch = vectorSearch;
    }

    public async Task<StepResult<QueryState>> ExecuteAsync(
        QueryState state,
        StepContext context,
        CancellationToken ct)
    {
        var results = await _vectorSearch.SearchAsync(
            query: state.Query,
            topK: 10,
            minRelevance: 0.7,
            ct);

        return state
            .With(s => s.RetrievedContext, results)
            .AsResult();
    }
}

SearchResult

Result from a vector similarity search.

Properties

PropertyTypeDescription
DocumentIdstringUnique identifier of matched document
ContentstringDocument text content
ScoredoubleSimilarity score (0.0 to 1.0)
MetadataDictionary<string, object>Additional document metadata

Example

csharp
var results = await _vectorSearch.SearchAsync(query, topK: 5, minRelevance: 0.7, ct);

foreach (var result in results)
{
    Console.WriteLine($"ID: {result.DocumentId}");
    Console.WriteLine($"Score: {result.Score:F3}");
    Console.WriteLine($"Content: {result.Content.Substring(0, 100)}...");

    if (result.Metadata.TryGetValue("source", out var source))
    {
        Console.WriteLine($"Source: {source}");
    }
}

Document

Represents a document for indexing.

Properties

PropertyTypeDescription
IdstringUnique document identifier
ContentstringText content to embed
Embeddingfloat[]?Pre-computed embedding (optional)
MetadataDictionary<string, object>Additional metadata

Example

csharp
var document = new Document
{
    Id = "doc-123",
    Content = "Agentic workflows combine deterministic state machines with AI agents...",
    Metadata = new Dictionary<string, object>
    {
        ["source"] = "documentation",
        ["chapter"] = "introduction",
        ["created"] = DateTimeOffset.UtcNow
    }
};

await _vectorSearch.UpsertAsync(document, ct);

Implemented Adapters

InMemoryVectorSearchAdapter

In-memory adapter for development and testing.

AspectValue
StatusAvailable
Use CaseDevelopment, unit testing, prototyping
PersistenceNone (data lost on restart)

Configuration

csharp
services.AddScoped<IVectorSearchAdapter, InMemoryVectorSearchAdapter>();

Limitations

  • No persistence between restarts
  • Not suitable for production
  • Limited scalability

Planned Adapters

PgVectorAdapter

PostgreSQL with pgvector extension.

AspectValue
StatusPlanned
Use CaseProduction with existing PostgreSQL
DependenciesPostgreSQL with pgvector extension

Planned Features

  • Leverages existing PostgreSQL infrastructure
  • HNSW and IVFFlat index support
  • Transactional consistency with workflow state

Planned Configuration

csharp
services.AddVectorSearch(options => options
    .UsePgVector(connectionString)
    .WithDimension(1536)
    .WithIndexType(IndexType.HNSW));

AzureAISearchAdapter

Azure AI Search for enterprise-scale deployments.

AspectValue
StatusPlanned
Use CaseEnterprise production, Azure ecosystem
DependenciesAzure AI Search service

Planned Features

  • Managed infrastructure
  • Hybrid search (vector + keyword)
  • Semantic ranking

Planned Configuration

csharp
services.AddVectorSearch(options => options
    .UseAzureAISearch(
        endpoint: "https://your-search.search.windows.net",
        apiKey: "your-api-key",
        indexName: "documents"));

RAG Workflow Patterns

Basic Retrieval

csharp
Workflow<QueryState>.Create("simple-rag")
    .StartWith<RetrieveContextStep>()
    .Then<GenerateResponseStep>()
    .Finally<FormatOutputStep>();

Retrieval with Reranking

csharp
Workflow<QueryState>.Create("reranked-rag")
    .StartWith<RetrieveContextStep>()
    .Then<RerankResultsStep>()
    .Then<GenerateResponseStep>()
    .Finally<FormatOutputStep>();

Multi-Query Retrieval

csharp
Workflow<QueryState>.Create("multi-query-rag")
    .StartWith<GenerateQueriesStep>()
    .Fork(
        path => path.Then<RetrieveForQuery1Step>(),
        path => path.Then<RetrieveForQuery2Step>(),
        path => path.Then<RetrieveForQuery3Step>())
    .Join<MergeResultsStep>()
    .Then<DeduplicateStep>()
    .Then<GenerateResponseStep>()
    .Finally<FormatOutputStep>();

Example: Complete RAG Step

csharp
public class RagQueryStep : IAgentStep<QueryState>
{
    private readonly IVectorSearchAdapter _vectorSearch;
    private readonly IChatClient _chatClient;

    public RagQueryStep(
        IVectorSearchAdapter vectorSearch,
        IChatClient chatClient)
    {
        _vectorSearch = vectorSearch;
        _chatClient = chatClient;
    }

    public async Task<StepResult<QueryState>> ExecuteAsync(
        QueryState state,
        AgentStepContext context,
        CancellationToken ct)
    {
        // Retrieve relevant context
        var searchResults = await _vectorSearch.SearchAsync(
            state.Query,
            topK: 5,
            minRelevance: 0.7,
            ct);

        // Build context string
        var contextText = string.Join("\n\n",
            searchResults.Select(r => r.Content));

        // Generate response with context
        var prompt = $"""
            Answer the following question using only the provided context.

            Context:
            {contextText}

            Question: {state.Query}

            Answer:
            """;

        var response = await _chatClient.GetResponseAsync(prompt, ct);

        return state
            .With(s => s.RetrievedContext, searchResults.ToList())
            .With(s => s.Response, response)
            .AsResult();
    }
}

Registration

csharp
// Development
services.AddScoped<IVectorSearchAdapter, InMemoryVectorSearchAdapter>();

// Production (when available)
services.AddVectorSearch(options => options
    .UsePgVector(connectionString)
    .WithEmbeddingClient<OpenAIEmbeddingClient>());

Released under the MIT License.