Skip to content

Commit

Permalink
Copilot comments search (#6786)
Browse files Browse the repository at this point in the history
* Add vector search for copilot comments

* Minor tweaks

* Remove unused code

* Add default search limit

* Add soft delete filter to search and make names more descriptive

* Add Cognitive Search

* Everything is fixed :D

* Fix everything

* Everything is NOW fixed
  • Loading branch information
yeojunh authored Aug 19, 2023
1 parent a5325e5 commit 736fca2
Show file tree
Hide file tree
Showing 8 changed files with 270 additions and 191 deletions.
2 changes: 1 addition & 1 deletion src/dotnet/APIView/APIViewWeb/APIViewWeb.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
<PackageReference Include="Azure.AI.OpenAI" Version="1.0.0-beta.6" />
<PackageReference Include="Azure.Data.AppConfiguration" Version="1.2.0" />
<PackageReference Include="Azure.Identity" Version="1.8.0" />
<PackageReference Include="Azure.Search.Documents" Version="11.4.0" />
<PackageReference Include="Azure.Search.Documents" Version="11.5.0-beta.4" />
<PackageReference Include="Azure.Storage.Blobs" Version="12.13.0" />
<PackageReference Include="CsvHelper" Version="27.2.1" />
<!-- Adding NU1701 suppression as these three libraries have not updated to more modern versions of .net, although in testing they work as required. -->
Expand Down
125 changes: 91 additions & 34 deletions src/dotnet/APIView/APIViewWeb/Controllers/CopilotCommentsController.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
using System.Text.Json;
using System.Threading.Tasks;
using APIViewWeb.Managers;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using APIViewWeb.Managers;
using System;
using Microsoft.Azure.Cosmos;
using APIViewWeb.Filters;

namespace APIViewWeb.Controllers
{
[TypeFilter(typeof(ApiKeyAuthorizeAsyncFilter))]

public class CopilotCommentsController : Controller
{
private readonly ICopilotCommentsManager _copilotManager;
Expand All @@ -19,73 +23,126 @@ public CopilotCommentsController(ICopilotCommentsManager copilotManager, ILogger
}

[HttpPost]
public async Task<ActionResult> CreateDocument(string badCode, string language, string goodCode = null, string comment = null, string[] guidelineIds = null)
public async Task<ActionResult> CreateDocument(string language, string badCode, string goodCode = null, string comment = null, string guidelineIds = null)
{
if (badCode == null)
if (badCode == null || language == null)
{
_logger.LogInformation("Request does not have the required badCode field for CREATE.");
return StatusCode(statusCode: StatusCodes.Status500InternalServerError);
_logger.LogInformation("Request does not have the required badCode or language fields for CREATE.");
return StatusCode(statusCode: StatusCodes.Status400BadRequest);
}

var id = await _copilotManager.CreateDocumentAsync(User.GetGitHubLogin(), badCode, goodCode, language, comment, guidelineIds);
_logger.LogInformation("Added a new document to database.");
return StatusCode(statusCode: StatusCodes.Status201Created, id);

try
{
var result = await _copilotManager.CreateDocumentAsync(language, badCode, goodCode, comment, guidelineIds, User.GetGitHubLogin());
_logger.LogInformation("Added a new document to database.");
return StatusCode(statusCode: StatusCodes.Status201Created, result);
}
catch (Exception err)
{
_logger.LogInformation("Error: unsuccessful CREATE request. " + err.Message);
return StatusCode(statusCode: StatusCodes.Status500InternalServerError);
}
}

[HttpPut]
public async Task<ActionResult> UpdateDocument(string id, string badCode = null, string language = null, string goodCode = null, string comment = null, string[] guidelineIds = null)
public async Task<ActionResult> UpdateDocument(string id, string language, string badCode = null, string goodCode = null, string comment = null, string guidelineIds = null)
{
if (id == null)
if (id == null || language == null)
{
_logger.LogInformation("Request does not have the required ID field for UPDATE.");
return StatusCode(statusCode: StatusCodes.Status500InternalServerError);
_logger.LogInformation("Request does not have the required ID or language fields for UPDATE.");
return StatusCode(statusCode: StatusCodes.Status400BadRequest);
}

var result = await _copilotManager.UpdateDocumentAsync(User.GetGitHubLogin(), id, badCode, goodCode, language, comment, guidelineIds);
if (result.ModifiedCount > 0)
try
{
_logger.LogInformation("Found existing document with ID. Updating document.");
var document = await _copilotManager.GetDocumentAsync(id);
return Ok(document);
} else
var result = await _copilotManager.UpdateDocumentAsync(id, language, badCode, goodCode, comment, guidelineIds, User.GetGitHubLogin());
return Ok(result);
}
catch (CosmosException)
{
_logger.LogInformation("Could not find a match for the given ID.");
_logger.LogInformation("Could not find a match for the given id and language combination.");
return StatusCode(statusCode: StatusCodes.Status404NotFound);
}
catch (Exception err)
{
_logger.LogInformation("Error: unsuccessful UPDATE request. " + err.Message);
return StatusCode(statusCode: StatusCodes.Status500InternalServerError);
}

}

[HttpGet]
public async Task<ActionResult> GetDocument(string id)
public async Task<ActionResult> GetDocument(string id, string language)
{
if (id == null)
if (id == null || language == null)
{
_logger.LogInformation("Request does not have the required ID field for GET.");
_logger.LogInformation("Request does not have the required ID or language fields for GET.");
return StatusCode(statusCode: StatusCodes.Status400BadRequest);
}

var document = await _copilotManager.GetDocumentAsync(id);
if (document != null)
try
{
return Ok(document);
} else
var result = await _copilotManager.GetDocumentAsync(id, language);
return Ok(result);
}
catch (CosmosException)
{
_logger.LogInformation("No document with this id exists in the database.");
_logger.LogInformation("Could not find a match for this id and language combination exists in the database.");
return StatusCode(statusCode: StatusCodes.Status404NotFound);
}
catch (Exception err)
{
_logger.LogInformation("Error: unsuccessful GET request. " + err.Message);
return StatusCode(statusCode: StatusCodes.Status500InternalServerError);
}

}

[HttpDelete]
public async Task<ActionResult> DeleteDocument(string id)
public async Task<ActionResult> DeleteDocument(string id, string language)
{
if (id == null || language == null)
{
_logger.LogInformation("Request does not have the required ID or language fields for DELETE.");
return StatusCode(statusCode: StatusCodes.Status400BadRequest);
}

try
{
await _copilotManager.DeleteDocumentAsync(id, language, User.GetGitHubLogin());
return StatusCode(statusCode: StatusCodes.Status204NoContent);
}
catch (CosmosException)
{
_logger.LogInformation("Could not find a match for this id and language combination exists in the database.");
return StatusCode(statusCode: StatusCodes.Status404NotFound);
}
catch (Exception err)
{
_logger.LogInformation("Error: unsuccessful DELETE request. " + err.Message);
return StatusCode(statusCode: StatusCodes.Status500InternalServerError);
}
}

[HttpGet]
public async Task<ActionResult> SearchDocument(string language, string code, float threshold, int? limit = null)
{
if (id == null)
if (language == null || code == null)
{
_logger.LogInformation("Request does not have the required ID field for DELETE.");
_logger.LogInformation("Request does not have the required code or language fields for SEARCH.");
return StatusCode(statusCode: StatusCodes.Status400BadRequest);
}

await _copilotManager.DeleteDocumentAsync(User.GetGitHubLogin(), id);
return StatusCode(statusCode: StatusCodes.Status204NoContent);
try
{
var topResults = await _copilotManager.SearchDocumentsAsync(language, code, threshold, limit ?? 5);
return Ok(topResults);
}
catch (Exception err)
{
_logger.LogInformation("Error: unsuccessful SEARCH request: " + err.Message);
return StatusCode(statusCode: StatusCodes.Status500InternalServerError);
}
}
}
}
Loading

0 comments on commit 736fca2

Please sign in to comment.