Skip to content

Commit 37c5651

Browse files
committed
Improve document services and WebAPI examples
1 parent 034bbe1 commit 37c5651

File tree

5 files changed

+246
-220
lines changed

5 files changed

+246
-220
lines changed

examples/WebAPI/Controllers/DocumentsController.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,10 @@ public IActionResult GetSupportedTypes()
6464
/// Upload multiple documents to the system
6565
/// </summary>
6666
[HttpPost("upload-multiple")]
67-
public async Task<ActionResult<List<Entities.Document>>> UploadDocuments(List<IFormFile> files)
67+
[Consumes("multipart/form-data")]
68+
[RequestSizeLimit(100 * 1024 * 1024)] // 100 MB
69+
[RequestFormLimits(MultipartBodyLengthLimit = 100 * 1024 * 1024)]
70+
public async Task<ActionResult<List<Entities.Document>>> UploadDocuments([FromForm] List<IFormFile> files)
6871
{
6972
if (files == null || files.Count == 0)
7073
return BadRequest("No files provided");
@@ -76,9 +79,9 @@ public IActionResult GetSupportedTypes()
7679
var contentTypes = files.Select(f => f.ContentType);
7780

7881
var documents = await documentService.UploadDocumentsAsync(
79-
fileStreams,
80-
fileNames,
81-
contentTypes,
82+
fileStreams,
83+
fileNames,
84+
contentTypes,
8285
"system");
8386

8487
return CreatedAtAction(nameof(GetAllDocuments), documents);
@@ -88,7 +91,6 @@ public IActionResult GetSupportedTypes()
8891
return StatusCode(500, $"Internal server error: {ex.Message}");
8992
}
9093
}
91-
9294
/// <summary>
9395
/// Get a document by ID
9496
/// </summary>

examples/WebAPI/Program.cs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
1-
using Microsoft.Extensions.Logging;
21
using Scalar.AspNetCore;
32
using SmartRAG.Enums;
43
using SmartRAG.Extensions;
4+
using Microsoft.OpenApi.Models;
5+
using SmartRAG.API.Filters;
56

67
var builder = WebApplication.CreateBuilder(args);
78

9+
// Configure Kestrel server options for file uploads
10+
builder.WebHost.UseKestrel(options =>
11+
{
12+
options.Limits.MaxRequestBodySize = 100 * 1024 * 1024; // 100 MB
13+
});
14+
815
RegisterServices(builder.Services, builder.Configuration);
916

1017
var app = builder.Build();
@@ -26,11 +33,27 @@ static void RegisterServices(IServiceCollection services, IConfiguration configu
2633
services.AddControllers();
2734
services.AddEndpointsApiExplorer();
2835
services.AddOpenApi();
36+
services.AddSwaggerGen(c =>
37+
{
38+
c.SwaggerDoc("v1", new OpenApiInfo { Title = "SmartRAG API", Version = "v1" });
39+
40+
// Configure multipart file upload for multiple files
41+
c.OperationFilter<MultipartFileUploadFilter>();
42+
});
43+
44+
// Configure form options for file uploads
45+
services.Configure<Microsoft.AspNetCore.Http.Features.FormOptions>(options =>
46+
{
47+
options.MultipartBodyLengthLimit = 100 * 1024 * 1024; // 100 MB
48+
options.ValueLengthLimit = int.MaxValue;
49+
options.ValueCountLimit = int.MaxValue;
50+
options.KeyLengthLimit = int.MaxValue;
51+
});
2952

3053
// Add SmartRag services with minimal configuration
3154
services.UseSmartRag(configuration,
3255
storageProvider: StorageProvider.InMemory, // Default: InMemory
33-
aiProvider: AIProvider.OpenAI // Use OpenAI provider
56+
aiProvider: AIProvider.Gemini // Use OpenAI provider
3457
);
3558

3659
services.AddCors(options =>
@@ -50,9 +73,13 @@ static void ConfigureMiddleware(WebApplication app, IWebHostEnvironment environm
5073
if (environment.IsDevelopment())
5174
{
5275
app.MapOpenApi();
53-
app.MapScalarApiReference();
76+
app.MapSwagger();
77+
app.UseSwaggerUI();
5478
}
5579

80+
// Serve static files for simple upload page
81+
app.UseStaticFiles();
82+
5683
app.UseHttpsRedirection();
5784
app.UseCors("AllowAll");
5885
app.UseAuthorization();

examples/WebAPI/SmartRAG.API.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
<ItemGroup>
1414
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.8" />
1515
<PackageReference Include="Scalar.AspNetCore" Version="2.6.9" />
16+
<PackageReference Include="Swashbuckle.AspNetCore" Version="9.0.3" />
1617
</ItemGroup>
1718

1819
</Project>

src/SmartRAG/Services/DocumentSearchService.cs

Lines changed: 42 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,23 @@
1010

1111
namespace SmartRAG.Services;
1212

13-
public class DocumentSearchService(
14-
IDocumentRepository documentRepository,
15-
IAIService aiService,
16-
IAIProviderFactory aiProviderFactory,
17-
IConfiguration configuration,
18-
SmartRagOptions options,
19-
ILogger<DocumentSearchService> logger) : IDocumentSearchService
20-
{
21-
22-
/// <summary>
23-
/// Sanitizes user input for safe logging by removing newlines and carriage returns.
24-
/// </summary>
25-
private static string SanitizeForLog(string input)
26-
{
27-
if (input == null) return string.Empty;
28-
return input.Replace("\r", "").Replace("\n", "");
29-
}
13+
public class DocumentSearchService(
14+
IDocumentRepository documentRepository,
15+
IAIService aiService,
16+
IAIProviderFactory aiProviderFactory,
17+
IConfiguration configuration,
18+
SmartRagOptions options,
19+
ILogger<DocumentSearchService> logger) : IDocumentSearchService
20+
{
21+
22+
/// <summary>
23+
/// Sanitizes user input for safe logging by removing newlines and carriage returns.
24+
/// </summary>
25+
private static string SanitizeForLog(string input)
26+
{
27+
if (input == null) return string.Empty;
28+
return input.Replace("\r", "").Replace("\n", "");
29+
}
3030
public async Task<List<DocumentChunk>> SearchDocumentsAsync(string query, int maxResults = 5)
3131
{
3232
if (string.IsNullOrWhiteSpace(query))
@@ -37,12 +37,12 @@ public async Task<List<DocumentChunk>> SearchDocumentsAsync(string query, int ma
3737

3838
if (searchResults.Count > 0)
3939
{
40-
ServiceLogMessages.LogSearchResults(logger, searchResults.Count, searchResults.Select(c => c.DocumentId).Distinct().Count(), null);
40+
ServiceLogMessages.LogSearchResults(logger, searchResults.Count, searchResults.Select(c => c.DocumentId).Distinct().Count(), null);
4141

42-
// Apply diversity selection to ensure chunks from different documents
43-
var diverseResults = ApplyDiversityAndSelect(searchResults, maxResults);
42+
// Apply diversity selection to ensure chunks from different documents
43+
var diverseResults = ApplyDiversityAndSelect(searchResults, maxResults);
4444

45-
ServiceLogMessages.LogDiverseResults(logger, diverseResults.Count, diverseResults.Select(c => c.DocumentId).Distinct().Count(), null);
45+
ServiceLogMessages.LogDiverseResults(logger, diverseResults.Count, diverseResults.Select(c => c.DocumentId).Distinct().Count(), null);
4646

4747
return diverseResults;
4848
}
@@ -55,11 +55,11 @@ public async Task<RagResponse> GenerateRagAnswerAsync(string query, int maxResul
5555
if (string.IsNullOrWhiteSpace(query))
5656
throw new ArgumentException("Query cannot be empty", nameof(query));
5757

58-
// Check if this is a general conversation query
59-
if (IsGeneralConversationQuery(query))
60-
{
61-
ServiceLogMessages.LogGeneralConversationQuery(logger, null);
62-
var chatResponse = await HandleGeneralConversationAsync(query);
58+
// Check if this is a general conversation query
59+
if (IsGeneralConversationQuery(query))
60+
{
61+
ServiceLogMessages.LogGeneralConversationQuery(logger, null);
62+
var chatResponse = await HandleGeneralConversationAsync(query);
6363
return new RagResponse
6464
{
6565
Answer = chatResponse,
@@ -75,21 +75,21 @@ public async Task<RagResponse> GenerateRagAnswerAsync(string query, int maxResul
7575

7676
public async Task<List<float>?> GenerateEmbeddingWithFallbackAsync(string text)
7777
{
78-
try
79-
{
80-
ServiceLogMessages.LogPrimaryAIServiceAttempt(logger, null);
81-
var result = await aiService.GenerateEmbeddingsAsync(text);
82-
if (result != null && result.Count > 0)
83-
{
84-
ServiceLogMessages.LogPrimaryAIServiceSuccess(logger, result.Count, null);
85-
return result;
86-
}
87-
ServiceLogMessages.LogPrimaryAIServiceNull(logger, null);
88-
}
89-
catch (Exception ex)
90-
{
91-
ServiceLogMessages.LogPrimaryAIServiceFailed(logger, ex);
92-
}
78+
try
79+
{
80+
ServiceLogMessages.LogPrimaryAIServiceAttempt(logger, null);
81+
var result = await aiService.GenerateEmbeddingsAsync(text);
82+
if (result != null && result.Count > 0)
83+
{
84+
ServiceLogMessages.LogPrimaryAIServiceSuccess(logger, result.Count, null);
85+
return result;
86+
}
87+
ServiceLogMessages.LogPrimaryAIServiceNull(logger, null);
88+
}
89+
catch (Exception ex)
90+
{
91+
ServiceLogMessages.LogPrimaryAIServiceFailed(logger, ex);
92+
}
9393

9494
var embeddingProviders = new[]
9595
{
@@ -208,7 +208,7 @@ public async Task<RagResponse> GenerateRagAnswerAsync(string query, int maxResul
208208
if (batchEmbeddings != null && batchEmbeddings.Count == texts.Count)
209209
return batchEmbeddings;
210210
}
211-
catch
211+
catch (Exception)
212212
{
213213
// Fallback to individual generation if batch fails
214214
}

0 commit comments

Comments
 (0)