-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Inject Kernel and AI services, then just use Kernel throughout, including for embedding generation - Remove use of Newtonsoft.Json - Use modern C# syntax, e.g. file-scoped namespaces, primary constructors, top-level statements, etc. - Fix logging to follow best practices, e.g. the logging string shouldn't vary on a given call site - Remove unnecessary fields/parameters/etc. - Address all warnings in project, e.g. nullable reference types - Fix formatting, e.g. inconsistent whitespace at the start of lines
- Loading branch information
1 parent
275bd0b
commit b30b97e
Showing
10 changed files
with
311 additions
and
528 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
28 changes: 8 additions & 20 deletions
28
src/ContosoChatAPI/ContosoChatAPI/Controllers/ContosoChatController.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,29 +1,17 @@ | ||
using ContosoChatAPI.Services; | ||
using Microsoft.AspNetCore.Mvc; | ||
|
||
namespace ContosoChatAPI.Controllers | ||
{ | ||
[ApiController] | ||
[Route("[controller]")] | ||
public class ContosoChatController : ControllerBase | ||
{ | ||
|
||
private readonly ILogger<ContosoChatController> _logger; | ||
private readonly ChatService chatService; | ||
|
||
public ContosoChatController(ILogger<ContosoChatController> logger, ChatService chatService) | ||
{ | ||
_logger = logger; | ||
this.chatService = chatService; | ||
} | ||
|
||
namespace ContosoChatAPI.Controllers; | ||
|
||
[ApiController] | ||
[Route("[controller]")] | ||
internal sealed class ContosoChatController(ILogger<ContosoChatController> logger, ChatService chatService) : ControllerBase | ||
{ | ||
[HttpPost(Name = "PostChatRequest")] | ||
public async Task<string> Post(string customerId, string question, List<string> chatHistory) | ||
{ | ||
string result = await chatService.GetResponseAsync(customerId, question, chatHistory.ToList()); | ||
_logger.LogInformation(result); | ||
return result; | ||
string result = await chatService.GetResponseAsync(customerId, question, chatHistory); | ||
logger.LogInformation("Result: {Result}", result); | ||
return result; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,63 +1,52 @@ | ||
using Azure.Search.Documents; | ||
using Azure.Search.Documents.Indexes; | ||
using Azure.Search.Documents.Models; | ||
using Azure.AI.OpenAI; | ||
|
||
namespace ContosoChatAPI.Data | ||
{ | ||
public class AISearchData | ||
{ | ||
private readonly SearchClient _searchClient; | ||
private readonly SearchIndexClient _searchIndexClient; | ||
readonly string _indexName; | ||
namespace ContosoChatAPI.Data; | ||
|
||
public AISearchData(IConfiguration config, SearchClient searchClient, SearchIndexClient searchIndexClient) | ||
{ | ||
_indexName = config["AzureAISearch:index_name"]; | ||
_searchClient = searchClient; | ||
_searchIndexClient = searchIndexClient; | ||
} | ||
internal sealed class AISearchData(SearchClient searchClient) | ||
{ | ||
private readonly SearchClient _searchClient = searchClient; | ||
|
||
public async Task<List<Dictionary<string, string>>> RetrieveDocumentationAsync( | ||
string question, | ||
Embeddings embedding) | ||
public async Task<List<Dictionary<string, string?>>> RetrieveDocumentationAsync(string question, ReadOnlyMemory<float> embedding) | ||
{ | ||
var searchOptions = new SearchOptions | ||
{ | ||
var searchOptions = new SearchOptions | ||
VectorSearch = new() | ||
{ | ||
VectorSearch = new() | ||
Queries = | ||
{ | ||
Queries = { | ||
new VectorizedQuery(embedding.Data[0].Embedding.ToArray()) { | ||
KNearestNeighborsCount = 3, | ||
Fields = { "contentVector" } } } | ||
}, | ||
Size = 3, | ||
Select = { "id", "title", "content", "url" }, | ||
QueryType = SearchQueryType.Semantic, | ||
SemanticSearch = new() | ||
{ | ||
SemanticConfigurationName = "default", | ||
QueryCaption = new(QueryCaptionType.Extractive), | ||
QueryAnswer = new(QueryAnswerType.Extractive), | ||
}, | ||
}; | ||
new VectorizedQuery(embedding) | ||
{ | ||
KNearestNeighborsCount = 3, | ||
Fields = { "contentVector" } | ||
} | ||
} | ||
}, | ||
Size = 3, | ||
Select = { "id", "title", "content", "url" }, | ||
QueryType = SearchQueryType.Semantic, | ||
SemanticSearch = new() | ||
{ | ||
SemanticConfigurationName = "default", | ||
QueryCaption = new(QueryCaptionType.Extractive), | ||
QueryAnswer = new(QueryAnswerType.Extractive), | ||
}, | ||
}; | ||
|
||
var results = await _searchClient.SearchAsync<SearchDocument>(question, searchOptions); | ||
var results = await _searchClient.SearchAsync<SearchDocument>(question, searchOptions); | ||
|
||
var docs = new List<Dictionary<string, string>>(); | ||
await foreach (var doc in results.Value.GetResultsAsync()) | ||
var docs = new List<Dictionary<string, string?>>(); | ||
await foreach (var doc in results.Value.GetResultsAsync()) | ||
{ | ||
docs.Add(new() | ||
{ | ||
var docInfo = new Dictionary<string, string> | ||
{ | ||
{ "id", doc.Document["id"].ToString() }, | ||
{ "title", doc.Document["title"].ToString() }, | ||
{ "content", doc.Document["content"].ToString() }, | ||
{ "url", doc.Document["url"].ToString() } | ||
}; | ||
docs.Add(docInfo); | ||
} | ||
|
||
return docs; | ||
{ "id", doc.Document["id"].ToString() }, | ||
{ "title", doc.Document["title"].ToString() }, | ||
{ "content", doc.Document["content"].ToString() }, | ||
{ "url", doc.Document["url"].ToString() } | ||
}); | ||
} | ||
|
||
return docs; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,46 +1,35 @@ | ||
using Microsoft.Azure.Cosmos; | ||
|
||
namespace ContosoChatAPI.Data | ||
{ | ||
public class CustomerData | ||
{ | ||
private readonly CosmosClient _cosmosClient; | ||
private readonly ILogger<CustomerData> logger; | ||
private readonly string _databaseName; | ||
private readonly string _containerName; | ||
namespace ContosoChatAPI.Data; | ||
|
||
public CustomerData(CosmosClient cosmosClient, ILogger<CustomerData> logger, IConfiguration config) | ||
{ | ||
_cosmosClient = cosmosClient; | ||
this.logger = logger; | ||
_databaseName = config["CosmosDb:databaseName"]; | ||
_containerName = config["CosmosDb:containerName"]; | ||
} | ||
internal sealed class CustomerData(CosmosClient cosmosClient, ILogger<CustomerData> logger, IConfiguration config) | ||
{ | ||
private readonly CosmosClient _cosmosClient = cosmosClient; | ||
private readonly ILogger<CustomerData> logger = logger; | ||
private readonly string _databaseName = config["CosmosDb:databaseName"]!; | ||
private readonly string _containerName = config["CosmosDb:containerName"]!; | ||
|
||
public async Task<Dictionary<string, object>> GetCustomerAsync(string customerId) | ||
public async Task<Dictionary<string, object>> GetCustomerAsync(string customerId) | ||
{ | ||
try | ||
{ | ||
var container = _cosmosClient.GetContainer(_databaseName, _containerName); | ||
var partitionKey = new PartitionKey(customerId); | ||
|
||
try | ||
{ | ||
var response = await container.ReadItemAsync<Dictionary<string, object>>(customerId, partitionKey); | ||
var customer = response.Resource; | ||
var response = await container.ReadItemAsync<Dictionary<string, object>>(customerId, new PartitionKey(customerId)); | ||
var customer = response.Resource; | ||
|
||
// Limit orders to the first 2 items | ||
if (customer.ContainsKey("orders") && customer["orders"] is List<object> orders) | ||
{ | ||
customer["orders"] = orders.Take(2).ToList(); | ||
} | ||
|
||
return customer; | ||
} | ||
catch (CosmosException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound) | ||
// Limit orders to the first 2 items | ||
if (customer.TryGetValue("orders", out object? orders) && orders is List<object> list) | ||
{ | ||
logger.LogError($"Customer with ID {customerId} not found."); | ||
throw; | ||
customer["orders"] = list.Take(2).ToList(); | ||
} | ||
} | ||
|
||
return customer; | ||
} | ||
catch (CosmosException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound) | ||
{ | ||
logger.LogError("Customer with ID {CustomerID} not found.", customerId); | ||
throw; | ||
} | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.