Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ ILogger<KernelMemory> logger

try
{
if (file == null)
{
logger.LogWarning("[{RequestId}] No file provided in request", requestId);
return Results.BadRequest(new DocumentImportedResult() { DocumentId = string.Empty });
}

var fileStream = file.OpenReadStream();
//Set Stream Position to 0
fileStream.Seek(0, SeekOrigin.Begin);
Expand Down Expand Up @@ -457,8 +463,6 @@ ILogger<KernelMemory> logger

//Creating While Loop with 10 mins timeout
var timeout = DateTime.UtcNow.AddMinutes(10);
var completeFlag = false;

var status = await kmClient.GetDocumentStatusAsync(documentId);

while (DateTime.UtcNow < timeout)
Expand All @@ -474,7 +478,6 @@ ILogger<KernelMemory> logger

if (status.RemainingSteps.Count == 0)
{
completeFlag = true;
break;
}
var totalSteps = status.Steps.Count;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace Microsoft.GS.DPSHost.API
{
public class UserInterface
{
private static Dictionary<string, byte[]> thumbnails = new Dictionary<string, byte[]>();
private static readonly Dictionary<string, byte[]> thumbnails = new Dictionary<string, byte[]>();

// Static method to register APIs
public static void AddAPIs(WebApplication app)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,12 @@ public void TrackEvent(string eventName, Dictionary<string, string>? properties
{
_telemetryClient.TrackEvent(eventName, properties, metrics);
}
#pragma warning disable CA1031 // Telemetry must never fail the calling code path
catch (Exception ex)
{
_logger.LogError(ex, "Failed to track event: {EventName}", eventName);
}
#pragma warning restore CA1031
}

/// <summary>
Expand All @@ -73,10 +75,12 @@ public void TrackException(Exception exception, Dictionary<string, string>? prop
{
_telemetryClient.TrackException(exception, properties, metrics);
}
#pragma warning disable CA1031 // Telemetry must never fail the calling code path
catch (Exception ex)
{
_logger.LogError(ex, "Failed to track exception");
}
#pragma warning restore CA1031
}

/// <summary>
Expand All @@ -96,12 +100,16 @@ public void TrackDependency(string dependencyName, string commandName, DateTimeO

try
{
_telemetryClient.TrackDependency(dependencyName, commandName, startTime, duration, success);
// Overload signature: TrackDependency(dependencyTypeName, target, dependencyName, data, startTime, duration, success)
// Map the wrapper's dependencyName -> telemetry dependencyName (and target), and commandName -> data.
_telemetryClient.TrackDependency("Other", dependencyName, dependencyName, commandName, startTime, duration, success ? "0" : "1", success);
}
#pragma warning disable CA1031 // Telemetry must never fail the calling code path
catch (Exception ex)
{
_logger.LogError(ex, "Failed to track dependency: {DependencyName}", dependencyName);
}
#pragma warning restore CA1031
}

/// <summary>
Expand Down Expand Up @@ -143,10 +151,12 @@ public void SetActivityTag(string key, string value)
{
Activity.Current?.SetTag(key, value);
}
#pragma warning disable CA1031 // Telemetry must never fail the calling code path
catch (Exception ex)
{
_logger.LogError(ex, "Failed to set activity tag: {Key}", key);
}
#pragma warning restore CA1031
}

/// <summary>
Expand All @@ -163,10 +173,12 @@ public void Flush()
{
_telemetryClient.Flush();
}
#pragma warning disable CA1031 // Telemetry must never fail the calling code path
catch (Exception ex)
{
_logger.LogError(ex, "Failed to flush telemetry client");
}
#pragma warning restore CA1031
}
}
}
25 changes: 13 additions & 12 deletions App/backend-api/Microsoft.GS.DPS/API/ChatHost/ChatHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,16 @@ internal static class JsonSerializationOptionsCache

public class ChatHost(MemoryWebClient kmClient, Kernel kernel, API.KernelMemory kernelMemory, ChatSessionRepository chatSessions)
{
private MemoryWebClient _kmClient = kmClient;
private Kernel _kernel = kernel;
private API.KernelMemory _kernelMemory = kernelMemory;
private IChatCompletionService _chatCompletionService = kernel.GetRequiredService<IChatCompletionService>();
private ChatSessionRepository _chatSessions = chatSessions;
private static string s_systemPrompt;
private static string s_assistancePrompt;
private static string s_additionalPrompt;
private readonly MemoryWebClient _kmClient = kmClient;
private readonly Kernel _kernel = kernel;
private readonly API.KernelMemory _kernelMemory = kernelMemory;
private readonly IChatCompletionService _chatCompletionService = kernel.GetRequiredService<IChatCompletionService>();
private readonly ChatSessionRepository _chatSessions = chatSessions;
private static readonly string s_systemPrompt;
private static readonly string s_assistancePrompt;
private static readonly string s_additionalPrompt;


string sessionId = string.Empty;
ChatHistory chatHistory = null;
ChatSession chatSession = null;

Expand All @@ -49,7 +48,7 @@ static ChatHost()
var assemblyLocation = Assembly.GetExecutingAssembly().Location;
var assemblyDirectory = System.IO.Path.GetDirectoryName(assemblyLocation);
// binding assembly directory with file path (Prompts/Chat_SystemPrompt.txt)
var systemPromptFilePath = System.IO.Path.Combine(assemblyDirectory, "Prompts", "Chat_SystemPrompt.txt");
var systemPromptFilePath = System.IO.Path.Join(assemblyDirectory, "Prompts", "Chat_SystemPrompt.txt");
ChatHost.s_systemPrompt = System.IO.File.ReadAllText(systemPromptFilePath);
ChatHost.s_assistancePrompt =
@"
Expand Down Expand Up @@ -84,7 +83,7 @@ private async Task<ChatSession> makeNewSession(string? chatSessionId)
//Create a new ChatSession Entity for Saving into Azure Cosmos
return new ChatSession()
{
SessionId = this.sessionId, // New Session ID
SessionId = sessionId, // New Session ID
StartTime = DateTime.UtcNow // Session Created Time
};

Expand Down Expand Up @@ -201,16 +200,18 @@ public async Task<ChatResponse> Chat(ChatRequest chatRequest)
Content = "Sorry, your request couldn't be processed as it may contain sensitive or restricted content. Please rephrase your query and try again."
};
}
#pragma warning disable CA1031 // Top-level chat-completion safety net: convert any failure to a user-facing fallback response
catch(Exception ex)
{
Console.WriteLine($"unexpected error: {ex.Message}");

returnedChatMessageContent = new ChatMessageContent
{
Content = "An error occured while processing request, try again"
Content = "An error occurred while processing request, try again"
};

}
#pragma warning restore CA1031
if (returnedChatMessageContent == null)
{
returnedChatMessageContent = new ChatMessageContent
Expand Down
37 changes: 26 additions & 11 deletions App/backend-api/Microsoft.GS.DPS/API/KernelMemory/KernelMemory.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using DnsClient.Internal;
using Microsoft.Extensions.Logging;
using Microsoft.GS.DPS.Images;
using Microsoft.GS.DPS.Model.KernelMemory;
using Microsoft.GS.DPS.Storage.Document;
Expand All @@ -23,28 +23,30 @@ namespace Microsoft.GS.DPS.API
{
public class KernelMemory
{
private MemoryWebClient _kmClient;
private DocumentRepository _documentRepository;
private DataCacheManager _dataCache;
private TagUpdater _tagUpdator;
private static string keywordExtractorPrompt = "";
private readonly MemoryWebClient _kmClient;
private readonly DocumentRepository _documentRepository;
private readonly DataCacheManager _dataCache;
private readonly TagUpdater _tagUpdator;
private readonly ILogger<KernelMemory>? _logger;
private static readonly string keywordExtractorPrompt = "";

static KernelMemory()
{
//Set Location of the System Prompt under running Assembly directory location.
var assemblyLocation = Assembly.GetExecutingAssembly().Location;
var assemblyDirectory = System.IO.Path.GetDirectoryName(assemblyLocation);
// binding assembly directory with file path (Prompts/KeywordExtract_SystemPrompt.txt)
var systemPromptFilePath = System.IO.Path.Combine(assemblyDirectory, "Prompts", "KeywordExtract_SystemPrompt.txt");
var systemPromptFilePath = System.IO.Path.Join(assemblyDirectory, "Prompts", "KeywordExtract_SystemPrompt.txt");
KernelMemory.keywordExtractorPrompt = System.IO.File.ReadAllText(systemPromptFilePath);
}

public KernelMemory(MemoryWebClient kmClient, DocumentRepository documentRepository, DataCacheManager dataCache, TagUpdater tagUpdator)
public KernelMemory(MemoryWebClient kmClient, DocumentRepository documentRepository, DataCacheManager dataCache, TagUpdater tagUpdator, ILogger<KernelMemory>? logger = null)
{
_kmClient = kmClient;
_documentRepository = documentRepository;
_dataCache = dataCache;
_tagUpdator = tagUpdator;
_logger = logger;
}

public async Task<DocumentImportedResult> ImportDocument(Stream documentStream,
Expand Down Expand Up @@ -139,7 +141,8 @@ private async Task<string> getSummary(string documentId, string fileName)
var summaryFile = await _kmClient.ExportFileAsync(documentId, summaryFileName);
var summaryFileStream = await summaryFile.GetStreamAsync();
// Read Stream to string
return await new StreamReader(summaryFileStream).ReadToEndAsync();
using var reader = new StreamReader(summaryFileStream);
return await reader.ReadToEndAsync();
}


Expand All @@ -151,7 +154,11 @@ private async Task<string> getSummary(string documentId, string fileName)
var keywordFile = await _kmClient.ExportFileAsync(documentId, keywordFileName);
var keywordFileStream = await keywordFile.GetStreamAsync();
// Read Stream to string
string? keywordContent = await new StreamReader(keywordFileStream).ReadToEndAsync();
string? keywordContent;
using (var reader = new StreamReader(keywordFileStream))
{
keywordContent = await reader.ReadToEndAsync();
}

if (string.IsNullOrEmpty(keywordContent))
{
Expand Down Expand Up @@ -196,10 +203,18 @@ private async Task<string> getSummary(string documentId, string fileName)

return keywordDict;
}
catch (Exception)
catch (JsonException ex)
{
_logger?.LogWarning(ex, "Failed to parse keyword JSON for document {DocumentId} ({FileName}); returning empty keyword set.", documentId, fileName);
return new Dictionary<string, string>();
}
#pragma warning disable CA1031 // LLM keyword-extraction output may be malformed; fall back to empty result rather than failing the import
catch (Exception ex)
{
_logger?.LogWarning(ex, "Failed to extract keywords for document {DocumentId} ({FileName}); returning empty keyword set.", documentId, fileName);
return new Dictionary<string, string>();
}
#pragma warning restore CA1031
Comment thread
Ayaz-Microsoft marked this conversation as resolved.
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,9 @@ public async Task RefreshCacheAsync()

var values = keywordDict.Value.Split(',').Select(v => v.Trim()).ToArray();

foreach (var value in values)
foreach (var value in values.Where(v => !consolidatedKeywords[keywordDict.Key].Contains(v)))
{
if (!consolidatedKeywords[keywordDict.Key].Contains(value))
{
consolidatedKeywords[keywordDict.Key].Add(value);
}
consolidatedKeywords[keywordDict.Key].Add(value);
}

consolidatedKeywords[keywordDict.Key] = consolidatedKeywords[keywordDict.Key].OrderBy(v => v).ToList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,12 @@ public async Task UpdateTags(string documentId, List<string> updatingTags)
var response = await _searchClient.MergeOrUploadDocumentsAsync(new[] { updateDocument });
Console.WriteLine($"Document with ID {document["id"]} updated successfully. - {response.GetRawResponse()}");
}
#pragma warning disable CA1031 // Tag update is best-effort; log and continue with the next document
catch (Exception ex)
{
Console.Error.WriteLine($"Error updating document with ID {document["id"]}: {ex.Message}");
}
#pragma warning restore CA1031
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,12 @@ public async Task<IEnumerable<TEntity>> FindAllAsync(ISpecification<TEntity> spe
{
var collection = _database.GetCollection<TEntity>(typeof(TEntity).Name.ToLowerInvariant());

GenericSpecification<TEntity> genericSpecification = specification as GenericSpecification<TEntity>;
if (specification is not GenericSpecification<TEntity> genericSpecification)
{
throw new ArgumentException(
$"Expected specification of type {nameof(GenericSpecification<TEntity>)}.",
nameof(specification));
}

if (genericSpecification.OrderBy == null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,9 +187,9 @@ async public Task<QueryResultSet> FindByDocumentIdsAsync(string[] documentIds,

if (endDate.HasValue)
{
endDate = endDate?.Date.AddHours(23).AddMinutes(59).AddSeconds(59);
var endOfDay = endDate.Value.Date.AddHours(23).AddMinutes(59).AddSeconds(59);
var timeFilter = Builders<Entities.Document>.Filter.Gte(x => x.ImportedTime, startDate ?? DateTime.Now) &
Builders<Entities.Document>.Filter.Lte(x => x.ImportedTime, endDate.Value);
Builders<Entities.Document>.Filter.Lte(x => x.ImportedTime, endOfDay);
filterDefinition &= timeFilter;
}

Expand Down
41 changes: 2 additions & 39 deletions App/frontend-app/src/components/chat/chatRoom.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
DialogSurface,
DialogTitle,
Tag,
makeStyles,
} from "@fluentui/react-components";
import { DocDialog } from "../documentViewer/documentViewer";
import { Textarea } from "@fluentai/textarea";
Expand All @@ -19,7 +18,7 @@ import { ChatAdd24Regular } from "@fluentui/react-icons";
import styles from "./chatRoom.module.scss";
import { CopilotProvider, Suggestion } from "@fluentai/react-copilot";
//import { getDocument } from "../../api/documentsService";
import { Completion, PostFeedback } from "../../api/chatService";
import { Completion } from "../../api/chatService";
import { FeedbackForm } from "./FeedbackForm";
import { Document } from "../../api/apiTypes/documentResults";
import { AppContext } from "../../AppContext";
Expand All @@ -29,12 +28,6 @@ import { renderToStaticMarkup } from "react-dom/server";
import { marked } from 'marked';
const DefaultChatModel = "chat_4o";

const useStyles = makeStyles({
tooltipContent: {
maxWidth: "500px",
},
});

interface ChatRoomProps {
searchResultDocuments: Document[];
disableOptionsPanel?: boolean;
Expand All @@ -52,7 +45,7 @@ export function ChatRoom({ searchResultDocuments, selectedDocuments, chatWithDoc
const [disableSources, setDisableSources] = useState<boolean>(false);
const [model, setModel] = useState<string>("chat_35");
const [source, setSource] = useState<string>("rag");
const [temperature, setTemperature] = useState<number>(0.8);
const [temperature] = useState<number>(0.8);
const [maxTokens] = useState<number>(750);
const [selectedDocument, setSelectedDocument] = useState<Document[]>(chatWithDocument);
const [button, setButton] = useState<string>("");
Expand Down Expand Up @@ -136,31 +129,6 @@ export function ChatRoom({ searchResultDocuments, selectedDocuments, chatWithDoc
currentSessionId = newSessionId; // Immediately use the new session ID in this function

}
const markdownToHtmlString = (markdown: string) => {
return renderToStaticMarkup(<ReactMarkdown>{markdown}</ReactMarkdown>);
};
const markdown = `| Data Point | Value | Document Name | Page Number |
|----------------|-----------|-------------------|------------------|
| Households with accessibility needs | 23.1 million | Accessibility in Housing Report | Page 1 |
| Households with mobility-related disabilities | 19% of U.S. households | Accessibility in Housing Report | Page 1 |
| Households without entry-level bedroom or full bathroom planning to add features | 1% | Accessibility in Housing Report | Page 3 |
| Households planning to make homes more accessible | 5% | Accessibility in Housing Report | Page 3 |
| Households with someone using mobility devices | 13% | Accessibility in Housing Report | Page 1 |
| Households with serious difficulty hearing | 12% | Accessibility in Housing Report | Page 24 |
| Households with serious difficulty seeing | 12% | Accessibility in Housing Report | Page 24 |
| Households with difficulty walking or climbing stairs | 12% | Accessibility in Housing Report | Page 24 |
| Households with difficulty dressing or bathing | 12% | Accessibility in Housing Report | Page 24 |
| Households with difficulty doing errands alone | 12% | Accessibility in Housing Report | Page 24 |
| Households with full bathrooms on entry level | 58% | Accessibility in Housing Report | Page 11 |
| Households with bedrooms on entry level | 46% | Accessibility in Housing Report | Page 11 |
| Total single-family loans acquired by Fannie Mae in 2021 | $2.6 trillion | Annual Housing Report 2022 | Page 36 |
| Total single-family loans acquired by Freddie Mac in 2021 | $2.6 trillion | Annual Housing Report 2022 | Page 36 |
| Percentage of loans with LTV > 95% | 13.5% | Annual Housing Report 2022 | Page 44 |
| Percentage of loans with LTV <= 60% | 15.6% | Annual Housing Report 2022 | Page 44 |
| Total NPLs sold by Enterprises through December 2023 | 168,364 | FHFA Non-Performing Loan Sales Report | Page 2 |
| Average delinquency of NPLs sold | 2.8 years | FHFA Non-Performing Loan Sales Report | Page 2 |
| Average current mark-to-market LTV ratio of NPLs | 83% | FHFA Non-Performing Loan Sales Report | Page 2 |`;


setConversationAnswers((prevAnswers) => [
...prevAnswers,
Expand Down Expand Up @@ -285,11 +253,6 @@ export function ChatRoom({ searchResultDocuments, selectedDocuments, chatWithDoc
// }
// };

const handleOpenFeedbackForm = (sources: Reference[]) => {
setReferencesForFeedbackForm(sources);
setIsFeedbackFormOpen(true);
};

const handleDialogClose = () => {
setIsDialogOpen(false);
};
Expand Down
Loading
Loading