๐ง Potato RAG Pipeline Quickstart Guide
This step-by-step guide will walk you through creating a Retrieval-Augmented Generation (RAG) API using Potato packages with MongoDB, MinIO (S3-compatible), Qdrant, and Mistral embeddings.
1. ๐ฏ Create the API Project
Add a new project to the Potato.Examples solution:
dotnet new web -n Potato.Examples.Api.Rag
dotnet sln add Potato.Examples.Api.Rag/Potato.Examples.Api.Rag.csproj
cd Potato.Examples.Api.Rag
dotnet new gitignore
2. ๐ฆ Install Required Packages
dotnet add package Potato
dotnet add package Potato.Mongo
dotnet add package Potato.Files.S3
dotnet add package Potato.Vectors.Qdrant
dotnet add package Potato.DocumentChopper
dotnet add package Potato.Embeddings.Mistral
dotnet add package Potato.RagPipeline
3. ๐ณ Add docker-compose.yml
version: "3.8"
services:
mongo:
image: mongo
ports:
- "27017:27017"
qdrant:
image: qdrant/qdrant
ports:
- "6333:6333"
- "6334:6334"
minio:
image: minio/minio
command: server /data --console-address ":9001"
ports:
- "9000:9000"
- "9001:9001"
environment:
MINIO_ROOT_USER: admin
MINIO_ROOT_PASSWORD: potato123
volumes:
- minio_data:/data
volumes:
minio_data:
Run the services:
docker compose up -d
4. โ๏ธ Add Configuration to appsettings.json
{
"ConnectionStrings": {
"MongoDbConnectionString": "mongodb://localhost:27017"
},
"PotatoS3Files": {
"ServiceUrl": "http://localhost:9000",
"AccessKey": "admin",
"SecretKey": "potato123",
"BucketName": "potato-dev",
"UseHttp": true
},
"PotatoQdrant": {
"Host": "localhost",
"Port": 6334
},
"Mistral": {
"ApiKey": "your-mistral-api-key"
}
}
5. ๐ Register Services in Program.cs
builder.Services
.AddApplicationLayer(typeof(Program).Assembly)
.AddMongoStandardGuidRepresentation()
.AddMongoDb(builder.Configuration, "chunks")
.AddMongoRepository<PotatoDocumentChunk>()
.AddMongoFinder<PotatoDocumentChunk>()
.AddPotatoS3Files(builder.Configuration)
.AddPotatoDocumentChopper()
.AddPotatoMarkdownConverter()
.AddPotatoMistralEmbeddings(builder.Configuration)
.AddPotatoQdrantVectors(builder.Configuration)
.AddPotatoRagPipeline();
var app = builder.Build();
await app.EnsureQdrantCollectionExists();
await app.EnsureS3BucketExists();
app.MapPost("/ingest", async (IFormFile file, IPotatoRagPipeline pipeline) =>
{
var result = await pipeline.Ingest(file, Map<string, string>(), contextId: Guid.NewGuid());
return result.Match(Results.Ok, f => Results.BadRequest(f.Message));
}).DisableAntiforgery();
app.MapGet("/search", async (string query, IPotatoRagPipeline pipeline) =>
{
var result = await pipeline.Retrieve(query);
return result.Match(Results.Ok, f => Results.BadRequest(f.Message));
});
app.MapGet("/message", async (string message, MistralClient client, IPotatoRagPipeline pipeline) =>
{
var result = await pipeline.Retrieve(message).GetOrThrow();
var request = new ChatCompletionRequest(
ModelDefinitions.MistralMedium,
[new ChatMessage(ChatMessage.RoleEnum.User, PromptBuilder.Build(result.Map(c => c.Text), message))]
);
return Results.Ok(new
{
Answer = await client.Completions.GetCompletionAsync(request),
ContextUsed = result,
SourceFiles = result.Map(r => new { r.FilePath, r.Index })
});
});
app.Run();
public class PromptBuilder
{
public static string Build(Lst<string> chunks, string userQuery)
{
if (chunks.IsEmpty)
{
return userQuery;
}
return $"""
Context information is below.
---------------------
{string.Join("\n\n", chunks)}
---------------------
Given the context information and not prior knowledge, answer the query.
Query: {userQuery}
Answer:
""";
}
}
6. ๐งช Test Using .http File
Create a new file named api.http in your project:
@hostname=localhost
@port=5297
### ๐ค Ingest a document (multipart upload)
POST http://{{hostname}}:{{port}}/ingest
Content-Type: multipart/form-data; boundary=---011000010111000001101001
-----011000010111000001101001
Content-Disposition: form-data; name="file"; filename="sample.txt"
Content-Type: text/plain
This is a simple test document. You can say hello and goodbye.
-----011000010111000001101001--
### ๐ Search chunks related to a query
GET http://{{hostname}}:{{port}}/search?query=how do i say hello
### ๐ฌ Ask a question and get a contextual answer
GET http://{{hostname}}:{{port}}/message?message=how do i say hello
Use the REST Client extension in VS Code to test these endpoints directly.
โ You're Done!
You now have a full RAG pipeline wired with Potato. ๐