-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8d89e2a
commit 8069c6d
Showing
18 changed files
with
361 additions
and
63 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
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 |
---|---|---|
@@ -0,0 +1,54 @@ | ||
namespace CookingApp.Controllers | ||
{ | ||
using CookingApp.Common; | ||
using CookingApp.Services.OpenAI.Completions; | ||
using Microsoft.AspNetCore.Authorization; | ||
using Microsoft.AspNetCore.Mvc; | ||
using OpenAI.ObjectModels.ResponseModels; | ||
|
||
[ApiController] | ||
[AllowAnonymous] | ||
public class GPTController : ControllerBase | ||
{ | ||
private readonly ICompletionService _completionService; | ||
private readonly ILogger<GPTController> _logger; | ||
|
||
public GPTController(ICompletionService completionService, ILogger<GPTController> logger) | ||
{ | ||
_completionService = completionService; | ||
_logger = logger; | ||
} | ||
|
||
[HttpPost("chat-request")] | ||
[AllowAnonymous] | ||
public async Task<IActionResult> SendQuery([FromBody] string message, [FromHeader] string? chatId = null) | ||
{ | ||
try | ||
{ | ||
_logger.LogInformation("Attempting ChatGPT API connection."); | ||
|
||
var result = | ||
String.IsNullOrEmpty(chatId) | ||
? await _completionService.CreateCompletion(message) | ||
: await _completionService.UpdateCompletion(message, chatId); | ||
|
||
if (result == null) | ||
{ | ||
return BadRequest(ExceptionMessages.ResponseRequestFailed); | ||
} | ||
|
||
_logger.LogInformation("Successfully connected to ChatGPT API."); | ||
_logger.LogInformation("Response received."); | ||
// To display the message you need to get into result.Choices[0].Message.Content. | ||
// The chat id is also contained inside the result | ||
|
||
return Ok(result); | ||
} | ||
catch (Exception ex) | ||
{ | ||
_logger.LogError("Failed attempt to contact ChatGPT API."); | ||
return BadRequest(ex.Message); | ||
} | ||
} | ||
} | ||
} |
11 changes: 11 additions & 0 deletions
11
src/server/CookingApp/Infrastructure/Configurations/OpenAI/OpenAIOptions.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 |
---|---|---|
@@ -0,0 +1,11 @@ | ||
namespace CookingApp.Infrastructure.Configurations.OpenAI | ||
{ | ||
public class OpenAIOptions | ||
{ | ||
public string APIKey { get; set; } | ||
|
||
public string APIUrl { get; set; } | ||
|
||
public string Model { get; set; } | ||
} | ||
} |
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
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 |
---|---|---|
@@ -0,0 +1,11 @@ | ||
using CookingApp.Infrastructure.Common; | ||
using MongoDB.Bson.Serialization.Attributes; | ||
|
||
public class Allergy : MongoEntity | ||
{ | ||
[BsonElement("name")] | ||
public string Name { get; set; } | ||
|
||
[BsonElement("severity")] | ||
public AllergySeverity Severity { get; set; } | ||
} |
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 |
---|---|---|
@@ -0,0 +1,6 @@ | ||
public enum AllergySeverity | ||
{ | ||
Mild, | ||
Moderate, | ||
Severe | ||
} |
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 |
---|---|---|
@@ -0,0 +1,14 @@ | ||
using CookingApp.Infrastructure.Common; | ||
using MongoDB.Bson.Serialization.Attributes; | ||
|
||
public class Chat : MongoEntity | ||
{ | ||
[BsonElement("createdTime")] | ||
public DateTime CreatedTime { get; set; } | ||
|
||
[BsonElement("requests")] | ||
public List<Request> Requests { get; set; } = new List<Request>(); | ||
|
||
[BsonElement("responses")] | ||
public List<Response> Responses { get; set; } = new List<Response>(); | ||
} |
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 |
---|---|---|
@@ -0,0 +1,6 @@ | ||
public enum DietaryPreference | ||
{ | ||
None, | ||
Vegan, | ||
Vegetarian | ||
} |
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 |
---|---|---|
@@ -0,0 +1,11 @@ | ||
using CookingApp.Infrastructure.Common; | ||
using MongoDB.Bson.Serialization.Attributes; | ||
|
||
public class Food : MongoEntity | ||
{ | ||
[BsonElement("name")] | ||
public string Name { get; set; } | ||
|
||
[BsonElement("type")] | ||
public FoodType Type { get; set; } | ||
} |
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 |
---|---|---|
@@ -0,0 +1,9 @@ | ||
public enum FoodType | ||
{ | ||
Vegetable, | ||
Fruit, | ||
Grain, | ||
Protein, | ||
Dairy, | ||
Other | ||
} |
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 |
---|---|---|
@@ -0,0 +1,11 @@ | ||
using CookingApp.Infrastructure.Common; | ||
using MongoDB.Bson.Serialization.Attributes; | ||
|
||
public class Request : MongoEntity | ||
{ | ||
[BsonElement("message")] | ||
public string Message { get; set; } | ||
|
||
[BsonElement("timestamp")] | ||
public DateTime Timestamp { get; set; } | ||
} |
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 |
---|---|---|
@@ -0,0 +1,11 @@ | ||
using CookingApp.Infrastructure.Common; | ||
using MongoDB.Bson.Serialization.Attributes; | ||
|
||
public class Response : MongoEntity | ||
{ | ||
[BsonElement("message")] | ||
public string Message { get; set; } | ||
|
||
[BsonElement("timestamp")] | ||
public DateTime Timestamp { get; set; } | ||
} |
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 |
---|---|---|
@@ -0,0 +1,26 @@ | ||
using MongoDB.Bson.Serialization.Attributes; | ||
using MongoDB.Bson; | ||
using System; | ||
using CookingApp.Infrastructure.Common; | ||
|
||
public class User : MongoEntity | ||
{ | ||
[BsonId] | ||
[BsonRepresentation(BsonType.ObjectId)] | ||
public string Id { get; set; } | ||
|
||
[BsonElement("name")] | ||
public string Name { get; set; } | ||
|
||
[BsonElement("dietaryPreference")] | ||
public DietaryPreference DietaryPreference { get; set; } | ||
|
||
[BsonElement("allergies")] | ||
public List<Allergy> Allergies { get; set; } = new List<Allergy>(); | ||
|
||
[BsonElement("avoidedFoods")] | ||
public List<Food> AvoidedFoods { get; set; } = new List<Food>(); | ||
|
||
[BsonElement("chats")] | ||
public List<Chat> Chats { get; set; } = new List<Chat>(); | ||
} |
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
128 changes: 128 additions & 0 deletions
128
src/server/CookingApp/Services/OpenAI/Completions/CompletionService.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 |
---|---|---|
@@ -0,0 +1,128 @@ | ||
namespace CookingApp.Services.OpenAI.Completions | ||
{ | ||
using global::OpenAI.Interfaces; | ||
using global::OpenAI.ObjectModels.ResponseModels; | ||
using global::OpenAI.ObjectModels.RequestModels; | ||
using global::OpenAI.ObjectModels; | ||
using CookingApp.Common.CompletionConstants; | ||
using CookingApp.Infrastructure.Interfaces; | ||
using System.Linq; | ||
|
||
/// <summary> | ||
/// This class it to assist with the personal needs of the user. | ||
/// After defining their dietary/allergic needs the chat completion | ||
/// will fill them in for the chatbot to take into account. | ||
/// </summary> | ||
public class CompletionService : ICompletionService | ||
{ | ||
private readonly IRepository<User> _userRepo; | ||
private readonly IRepository<Chat> _chatRepo; | ||
private readonly IOpenAIService _openAIService; | ||
|
||
public CompletionService(IOpenAIService openAIService, IRepository<User> userRepo, IRepository<Chat> chatRepo) | ||
{ | ||
_openAIService = openAIService; | ||
_userRepo = userRepo; | ||
_chatRepo = chatRepo; | ||
} | ||
|
||
public async Task<ChatCompletionCreateResponse> CreateCompletion(string request) | ||
{ | ||
//TODO: get the userId through JWT Bearer | ||
var user = await _userRepo.GetByIdAsync("userId"); | ||
|
||
// Get the user allergies | ||
var userAllergies = user.Allergies; | ||
|
||
// Case if the converstaion is new and the chat doesn't exist | ||
var completionResult = await _openAIService.ChatCompletion.CreateCompletion(new ChatCompletionCreateRequest | ||
{ | ||
Messages = new List<ChatMessage> | ||
{ | ||
// Creating a prompt for the chatboot to answer a question about cooking/diatery needs. | ||
ChatMessage.FromSystem(Completions.Instructions | ||
+ userAllergies + "." | ||
+ Completions.PromptEngineeringPrevention), | ||
ChatMessage.FromUser(Completions.Suggestion), | ||
ChatMessage.FromAssistant(Completions.ExampleResponse), | ||
ChatMessage.FromUser(request) | ||
}, | ||
Model = Models.Gpt_4o | ||
}); | ||
|
||
var userChat = CreateNewChat(completionResult.Id); | ||
|
||
if (completionResult.Successful) | ||
{ | ||
var response = completionResult.Choices[0].Message.Content; | ||
UpdateUserChat(userChat, request, response); | ||
return completionResult; | ||
} | ||
|
||
return null; | ||
|
||
} | ||
|
||
public async Task<ChatCompletionCreateResponse> UpdateCompletion(string request, string? chatId = null) | ||
{ | ||
var userChat = await _chatRepo.GetByIdAsync(chatId); | ||
|
||
var completionResult = await _openAIService.ChatCompletion.CreateCompletion(new ChatCompletionCreateRequest | ||
{ | ||
Messages = new List<ChatMessage> | ||
{ | ||
ChatMessage.FromUser(request) | ||
}, | ||
Model = Models.Gpt_4o | ||
}); | ||
|
||
if (completionResult.Successful) | ||
{ | ||
var response = completionResult.Choices[0].Message.Content; | ||
UpdateUserChat(userChat, request, response); | ||
return completionResult; | ||
} | ||
|
||
return null; | ||
} | ||
|
||
private static bool ChatExists(string chatID, User? user) | ||
=> user.Chats.Any(x => x.Id == chatID); | ||
|
||
private Request CreateNewRequest(string message) | ||
=> new Request() | ||
{ | ||
Message = message, | ||
Timestamp = DateTime.UtcNow, | ||
}; | ||
|
||
private Response CreateNewResponse(string message) | ||
=> new Response() | ||
{ | ||
Message = message, | ||
Timestamp = DateTime.UtcNow, | ||
}; | ||
|
||
// Creates a new chat using the ID originating from the ChatGPT API | ||
private Chat CreateNewChat(string id) | ||
{ | ||
var chat = new Chat() | ||
{ | ||
Id = id, | ||
Requests = new List<Request>(), | ||
Responses = new List<Response>() | ||
}; | ||
|
||
_chatRepo.InsertAsync(chat); | ||
|
||
return chat; | ||
} | ||
|
||
private async void UpdateUserChat(Chat? userChat, string? request, string? response) | ||
{ | ||
userChat.Requests.Add(CreateNewRequest(request)); | ||
userChat.Responses.Add(CreateNewResponse(response)); | ||
await _chatRepo.UpdateAsync(userChat); | ||
} | ||
} | ||
} |
11 changes: 11 additions & 0 deletions
11
src/server/CookingApp/Services/OpenAI/Completions/ICompletionService.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 |
---|---|---|
@@ -0,0 +1,11 @@ | ||
namespace CookingApp.Services.OpenAI.Completions | ||
{ | ||
using global::OpenAI.ObjectModels.ResponseModels; | ||
|
||
public interface ICompletionService | ||
{ | ||
Task<ChatCompletionCreateResponse> CreateCompletion(string message); | ||
|
||
Task<ChatCompletionCreateResponse> UpdateCompletion(string request, string? chatId = null); | ||
} | ||
} |
Oops, something went wrong.