diff --git a/Controllers/QuoteController.cs b/Controllers/QuoteController.cs
index fc3cce2..8e6ed28 100644
--- a/Controllers/QuoteController.cs
+++ b/Controllers/QuoteController.cs
@@ -2,6 +2,7 @@ using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
+using Newtonsoft.Json.Linq;
using QuotifyBE.Data;
using QuotifyBE.DTOs;
using QuotifyBE.Entities;
@@ -481,4 +482,75 @@ public class QuotesController : ControllerBase
return Ok(quote.ToQuoteShortDTO());
}
+ // POST /api/v1/quotes/ai
+ ///
+ /// [AUTHED] Request a LLM-generated quote
+ ///
+ /// Generated quote's text
+ ///
+ /// Notes:
+ ///
+ ///
+ /// If customPrompt is passed:
+ /// - The default prompt is overriden by whatever has been passed by the user.
+ ///
+ ///
+ ///
+ /// If model is passed:
+ /// - The default large language model is overriden by whatever has been passed by the user.
+ ///
+ ///
+ ///
+ /// If temperature is passed:
+ /// - The default temperature (= 0.8) is overriden by whatever has been passed by the user.
+ ///
+ ///
+ ///
+ /// If categoryId is passed:
+ /// - The prompt is appended with an instruction in Polish to generate quotes based on the provided category
+ /// (both name and description get passed to the model).
+ /// - Heads up! The text is appended even if customPrompt has been provided.
+ ///
+ ///
+ ///
+ /// If useSampleQuote is passed:
+ /// - The prompt will be appended with a randomly chosen quote from the categoryId (if any exist),
+ /// thus passing categoryId becomes a prerequisite.
+ /// - Heads up! The request will fail returning status code 400 if categoryId isn't provided!
+ ///
+ ///
+ /// Form data containing required quote information
+ /// Returned on valid request
+ /// Returned when generation failed due to remote server error (likely because of a bad request)
+ /// Returned when response has been generated, but couldn't be parsed (likely because of incompatible server or bad URL)
+ [HttpPost("ai")]
+ [Authorize]
+ [EnableCors]
+ [ProducesResponseType(200)]
+ [ProducesResponseType(typeof(ErrorDTO), 400)]
+ [ProducesResponseType(typeof(ErrorDTO), 500)]
+ public async Task CreateLLMQuote([FromBody] AskLLMInDTO request)
+ {
+
+ JObject? generatedResponse = await guhf.GenerateLLMResponse(
+ request.CustomPrompt, request.Model, request.Temperature, request.CategoryId, request.UseSampleQuote
+ );
+
+ // Check if any errors occurred
+ if (generatedResponse == null)
+ {
+ return StatusCode(400, new ErrorDTO { Status = "error", Error_msg = "Generation failed most likely due to bad request" });
+ }
+
+ // Parse JSON to get the bot reply
+ string? llmResponse = generatedResponse["choices"]?[0]?["message"]?["content"]?.ToString().Trim('"');
+
+ // If response string is not where we expect it, return 500
+ if (llmResponse == null)
+ return StatusCode(500, new ErrorDTO { Status = "error", Error_msg = "Unexpected API response" });
+
+ // Otherwise, return the response
+ return Ok(new { Status = "ok", BotResponse = llmResponse });
+ }
+
}