Skip to content

Commit 1bd5da3

Browse files
committed
Add EnhancedMockDataBackend and RssFeedService for improved data handling
- Implement EnhancedMockDataBackend to provide strict data source isolation based on LLM availability, ensuring clean results from live RSS feeds and mock data. - Introduce RssFeedService for fetching and parsing RSS feeds, including methods for retrieving latest blog posts and feed items. - Update MockDataBackend with new sample data focused on science fiction themes, including spacecraft, blog content, movies, events, and futuristic recipes. - Remove outdated endpoint test file to streamline project structure.
1 parent 416d2c1 commit 1bd5da3

File tree

8 files changed

+807
-238
lines changed

8 files changed

+807
-238
lines changed

samples/Demo/Components/Pages/NLWebDemo.razor

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,36 @@
4444
</div>
4545
}
4646

47-
<div class="col-lg-6">
48-
@if (AIConfigService.IsAIConfigured)
47+
<div class="col-lg-6"> @if (AIConfigService.IsAIConfigured)
4948
{
5049
<div class="alert alert-success mb-3">
5150
<i class="fas fa-check-circle me-2"></i>
5251
<strong>AI Provider:</strong> @AIConfigService.GetCurrentProvider()
5352
</div>
53+
54+
<div class="alert alert-info mb-3">
55+
<h6 class="mb-2"><i class="fas fa-lightbulb me-2"></i>What can you search for?</h6>
56+
<div class="row g-2">
57+
<div class="col-md-6">
58+
<div class="d-flex align-items-center mb-1">
59+
<i class="fas fa-rss text-primary me-2"></i>
60+
<strong>.NET Content</strong>
61+
</div>
62+
<small class="text-muted ms-3">
63+
Try: ".NET 9", "ASP.NET updates", "C# features"
64+
</small>
65+
</div>
66+
<div class="col-md-6">
67+
<div class="d-flex align-items-center mb-1">
68+
<i class="fas fa-rocket text-info me-2"></i>
69+
<strong>Science Fiction</strong>
70+
</div>
71+
<small class="text-muted ms-3">
72+
Try: "space movies", "Mars exploration", "AI stories"
73+
</small>
74+
</div>
75+
</div>
76+
</div>
5477
}
5578

5679
<QueryInput OnSubmit="HandleQuerySubmitted" IsLoading="isLoading" @ref="queryInputComponent" />

samples/Demo/Components/ResultsDisplay.razor

Lines changed: 131 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,70 @@
1616
<small class="text-muted">Query ID: @Response.QueryId</small>
1717
</div>
1818
</div>
19+
20+
@* Data Source Indicators - Top Level Design Element *@
21+
@if (Response.Results?.Any() == true)
22+
{
23+
<div class="card-body border-bottom bg-light">
24+
<h6 class="mb-3"><i class="fas fa-database me-2"></i>Data Sources</h6>
25+
<div class="row g-3">
26+
@{
27+
var rssCount = Response.Results.Count(r => r.Site == "devblogs.microsoft.com");
28+
var mockCount = Response.Results.Count(r => r.Name.StartsWith("[Mock Data]"));
29+
var staticCount = Response.Results.Count - rssCount - mockCount;
30+
}
31+
32+
@* RSS Feed Data Source *@
33+
<div class="col-md-4">
34+
<div class="card h-100 @(rssCount > 0 ? "border-primary" : "border-secondary opacity-50")">
35+
<div class="card-body text-center">
36+
<div class="mb-2">
37+
<i class="fas fa-rss fa-2x @(rssCount > 0 ? "text-primary" : "text-secondary")"></i>
38+
</div>
39+
<h6 class="card-title">Live RSS Feeds</h6>
40+
<p class="card-text small text-muted">.NET Blog & News</p>
41+
<span class="badge @(rssCount > 0 ? "bg-primary" : "bg-secondary")">
42+
@rssCount result(s)
43+
</span>
44+
</div>
45+
</div>
46+
</div>
47+
48+
@* Static Schema.org Data Source *@
49+
<div class="col-md-4">
50+
<div class="card h-100 @(staticCount > 0 ? "border-info" : "border-secondary opacity-50")">
51+
<div class="card-body text-center">
52+
<div class="mb-2">
53+
<i class="fas fa-rocket fa-2x @(staticCount > 0 ? "text-info" : "text-secondary")"></i>
54+
</div>
55+
<h6 class="card-title">Schema.org Static Data</h6>
56+
<p class="card-text small text-muted">Science Fiction Content</p>
57+
<span class="badge @(staticCount > 0 ? "bg-info" : "bg-secondary")">
58+
@staticCount result(s)
59+
</span>
60+
</div>
61+
</div>
62+
</div>
63+
64+
@* Mock Data Source *@
65+
<div class="col-md-4">
66+
<div class="card h-100 @(mockCount > 0 ? "border-warning" : "border-secondary opacity-50")">
67+
<div class="card-body text-center">
68+
<div class="mb-2">
69+
<i class="fas fa-flask fa-2x @(mockCount > 0 ? "text-warning" : "text-secondary")"></i>
70+
</div>
71+
<h6 class="card-title">Mock Data</h6>
72+
<p class="card-text small text-muted">Placeholder Content</p>
73+
<span class="badge @(mockCount > 0 ? "bg-warning" : "bg-secondary")">
74+
@mockCount result(s)
75+
</span>
76+
</div>
77+
</div>
78+
</div>
79+
</div>
80+
</div>
81+
}
82+
1983
<div class="card-body">
2084
@if (!string.IsNullOrEmpty(Response.Summary))
2185
{
@@ -77,14 +141,17 @@
77141
}
78142
</h6>
79143
<span class="badge bg-primary">@result.Score.ToString("F2")</span>
80-
</div>
81-
@if (!string.IsNullOrEmpty(result.Description))
144+
</div> @if (!string.IsNullOrEmpty(result.Description))
82145
{
83-
<p class="card-text small">@result.Description</p>
84-
}
85-
@if (!string.IsNullOrEmpty(result.Site))
146+
<p class="card-text small">@((MarkupString)FormatDescription(result))</p>
147+
} @if (!string.IsNullOrEmpty(result.Site))
86148
{
87149
<div class="mt-2">
150+
@{
151+
var badgeClass = GetDataSourceBadgeClass(result);
152+
var sourceLabel = GetDataSourceLabel(result);
153+
}
154+
<span class="badge @badgeClass me-1">@sourceLabel</span>
88155
<span class="badge bg-secondary">@result.Site</span>
89156
</div>
90157
}
@@ -115,18 +182,21 @@
115182
{
116183
@result.Name
117184
}
118-
</h6>
119-
<div>
185+
</h6> <div>
120186
<span class="badge bg-primary me-2">@result.Score.ToString("F2")</span>
187+
@{
188+
var badgeClass = GetDataSourceBadgeClass(result);
189+
var sourceLabel = GetDataSourceLabel(result);
190+
}
191+
<span class="badge @badgeClass me-1">@sourceLabel</span>
121192
@if (!string.IsNullOrEmpty(result.Site))
122193
{
123194
<span class="badge bg-secondary">@result.Site</span>
124195
}
125196
</div>
126-
</div>
127-
@if (!string.IsNullOrEmpty(result.Description))
197+
</div> @if (!string.IsNullOrEmpty(result.Description))
128198
{
129-
<p class="mb-1 small">@result.Description</p>
199+
<p class="mb-1 small">@((MarkupString)FormatDescription(result))</p>
130200
}
131201
</div>
132202
}
@@ -236,9 +306,7 @@
236306
.Replace("**", "</strong>");
237307

238308
return formatted;
239-
}
240-
241-
private string FormatJson(object? obj)
309+
} private string FormatJson(object? obj)
242310
{
243311
if (obj == null) return "null";
244312

@@ -253,5 +321,55 @@
253321
{
254322
return obj.ToString() ?? "null";
255323
}
324+
} private string FormatDescription(NLWebResult result)
325+
{
326+
if (string.IsNullOrEmpty(result.Description))
327+
return "";
328+
329+
var description = result.Description;
330+
331+
// Remove HTML tags ONLY for RSS content from devblogs.microsoft.com
332+
if (result.Site == "devblogs.microsoft.com")
333+
{
334+
description = StripHtmlTags(description);
335+
}
336+
337+
return description;
338+
}private bool IsRssContent(NLWebResult result)
339+
{
340+
// RSS content is ONLY from devblogs.microsoft.com
341+
// Static sci-fi content should NOT be considered RSS even if it has BlogPosting type
342+
return result.Site == "devblogs.microsoft.com";
343+
}
344+
345+
private string StripHtmlTags(string html)
346+
{
347+
if (string.IsNullOrEmpty(html))
348+
return "";
349+
350+
// Basic HTML tag removal - removes anything between < and >
351+
return System.Text.RegularExpressions.Regex.Replace(html, "<.*?>", string.Empty);
352+
}
353+
354+
private string GetDataSourceBadgeClass(NLWebResult result)
355+
{
356+
if (result.Name.StartsWith("[Mock Data]"))
357+
return "bg-warning";
358+
359+
if (result.Site == "devblogs.microsoft.com" || IsRssContent(result))
360+
return "bg-primary";
361+
362+
return "bg-info"; // Static Schema.org content
363+
}
364+
365+
private string GetDataSourceLabel(NLWebResult result)
366+
{
367+
if (result.Name.StartsWith("[Mock Data]"))
368+
return "Mock";
369+
370+
if (result.Site == "devblogs.microsoft.com" || IsRssContent(result))
371+
return "RSS";
372+
373+
return "Schema.org"; // Static content
256374
}
257375
}

samples/Demo/NLWebNet.Demo.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@
1616
<ContainerWorkingDirectory>/app</ContainerWorkingDirectory>
1717
</PropertyGroup>
1818
<ItemGroup>
19-
<ProjectReference Include="..\..\src\NLWebNet\NLWebNet.csproj" />
20-
</ItemGroup><ItemGroup>
19+
<ProjectReference Include="..\..\src\NLWebNet\NLWebNet.csproj" /> </ItemGroup><ItemGroup>
2120
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.6" />
21+
<PackageReference Include="System.ServiceModel.Syndication" Version="8.0.0" />
2222
</ItemGroup>
2323

2424
</Project>

samples/Demo/Program.cs

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using NLWebNet;
33
using NLWebNet.Extensions;
44
using NLWebNet.Endpoints;
5+
using NLWebNet.Demo.Services;
56

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

@@ -29,20 +30,8 @@
2930
return factory.GetChatClient() ?? new NLWebNet.Demo.Services.NullChatClient();
3031
});
3132

32-
// Explicitly use MockDataBackend to test if WebSearchBackend is causing the hang
33-
builder.Services.AddScoped<NLWebNet.Services.IDataBackend>(serviceProvider =>
34-
{
35-
var logger = serviceProvider.GetRequiredService<ILogger<NLWebNet.Services.MockDataBackend>>();
36-
return new NLWebNet.Services.MockDataBackend(logger);
37-
});
38-
39-
// Temporarily use MockDataBackend to test if WebSearchBackend is causing the hang
40-
// builder.Services.AddScoped<NLWebNet.Services.IDataBackend>(serviceProvider =>
41-
// {
42-
// var logger = serviceProvider.GetRequiredService<ILogger<NLWebNet.Demo.Services.WebSearchBackend>>();
43-
// var httpClient = serviceProvider.GetRequiredService<HttpClient>();
44-
// return new NLWebNet.Demo.Services.WebSearchBackend(logger, httpClient);
45-
// });
33+
// Add RSS feed service for dynamic content
34+
builder.Services.AddScoped<IRssFeedService, RssFeedService>();
4635

4736
// Add CORS configuration
4837
builder.Services.AddCors(options =>
@@ -93,6 +82,11 @@
9382
});
9483
}
9584

85+
// IMPORTANT: Override the default MockDataBackend with our enhanced version AFTER AddNLWebNet
86+
// Use enhanced data backend with RSS feed integration and better sample data
87+
builder.Services.AddScoped<NLWebNet.Services.IDataBackend, EnhancedMockDataBackend>();
88+
Console.WriteLine("Registered EnhancedMockDataBackend as IDataBackend service (overriding default)");
89+
9690
// Add OpenAPI for API documentation
9791
builder.Services.AddOpenApi();
9892

0 commit comments

Comments
 (0)