diff --git a/ChatGemini/ChatGemini.csproj b/ChatGemini/ChatGemini.csproj
new file mode 100644
index 0000000..e5252f5
--- /dev/null
+++ b/ChatGemini/ChatGemini.csproj
@@ -0,0 +1,17 @@
+
+
+
+ net8.0
+ enable
+ enable
+ ChatServerSpace
+ ChatServerSpace
+
+
+
+
+
+
+
+
+
diff --git a/ChatGemini/ChatGemini.http b/ChatGemini/ChatGemini.http
new file mode 100644
index 0000000..29dacad
--- /dev/null
+++ b/ChatGemini/ChatGemini.http
@@ -0,0 +1,6 @@
+@ChatGemini_HostAddress = http://localhost:5004
+
+GET {{ChatGemini_HostAddress}}/weatherforecast/
+Accept: application/json
+
+###
diff --git a/ChatGemini/Controllers/ChatController.cs b/ChatGemini/Controllers/ChatController.cs
new file mode 100644
index 0000000..dfb0919
--- /dev/null
+++ b/ChatGemini/Controllers/ChatController.cs
@@ -0,0 +1,45 @@
+using ChatServerSpace.Models;
+using ChatServerSpace.Services;
+using Microsoft.AspNetCore.Mvc;
+
+namespace ChatServerSpace.Controllers
+{
+ [ApiController]
+ [Route("api/[controller]")]
+ public class ChatController : ControllerBase
+ {
+ private readonly IChatService _chatService;
+ private readonly ILogger _logger;
+
+ public ChatController(IChatService chatService, ILogger logger)
+ {
+ _chatService = chatService;
+ _logger = logger;
+ }
+
+ [HttpPost]
+ public async Task> Chat([FromBody] ChatRequest request)
+ {
+ if (string.IsNullOrWhiteSpace(request.SessionId))
+ {
+ return BadRequest("SessionId is required");
+ }
+
+ if (string.IsNullOrWhiteSpace(request.Message))
+ {
+ return BadRequest("Message is required");
+ }
+
+ try
+ {
+ var response = await _chatService.ProcessMessageAsync(request);
+ return Ok(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error processing chat message");
+ return StatusCode(500, "An error occurred while processing your message");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ChatGemini/Models/ChatMessage.cs b/ChatGemini/Models/ChatMessage.cs
new file mode 100644
index 0000000..cb45bf9
--- /dev/null
+++ b/ChatGemini/Models/ChatMessage.cs
@@ -0,0 +1,18 @@
+using MongoDB.Bson.Serialization.Attributes;
+using MongoDB.Bson;
+using ThirdParty.Json.LitJson;
+
+namespace ChatServerSpace.Models
+{
+ public class ChatMessage
+ {
+ [BsonElement("_id")]
+ [BsonId]
+ [BsonRepresentation(BsonType.ObjectId)]
+ public string? Id { get; set; }
+ public string SessionId { get; set; } = string.Empty;
+ public string Role { get; set; } = string.Empty;
+ public string Content { get; set; } = string.Empty;
+ public DateTime Timestamp { get; set; } = DateTime.UtcNow;
+ }
+}
diff --git a/ChatGemini/Models/ChatRequest.cs b/ChatGemini/Models/ChatRequest.cs
new file mode 100644
index 0000000..13fe482
--- /dev/null
+++ b/ChatGemini/Models/ChatRequest.cs
@@ -0,0 +1,8 @@
+namespace ChatServerSpace.Models
+{
+ public class ChatRequest
+ {
+ public required string SessionId { get; set; }
+ public required string Message { get; set; }
+ }
+}
diff --git a/ChatGemini/Models/ChatResponse.cs b/ChatGemini/Models/ChatResponse.cs
new file mode 100644
index 0000000..c9c470d
--- /dev/null
+++ b/ChatGemini/Models/ChatResponse.cs
@@ -0,0 +1,8 @@
+namespace ChatServerSpace.Models
+{
+ public class ChatResponse
+ {
+ public required string SessionId { get; set; }
+ public required string Response { get; set; }
+ }
+}
diff --git a/ChatGemini/Program.cs b/ChatGemini/Program.cs
new file mode 100644
index 0000000..6c526b9
--- /dev/null
+++ b/ChatGemini/Program.cs
@@ -0,0 +1,30 @@
+using ChatServerSpace.Services;
+
+var builder = WebApplication.CreateBuilder(args);
+
+// Add services to the container.
+builder.Services.AddControllers();
+builder.Services.AddEndpointsApiExplorer();
+builder.Services.AddSwaggerGen();
+builder.Services.AddHttpClient();
+
+// Register services
+builder.Services.AddSingleton();
+builder.Services.AddScoped();
+
+var app = builder.Build();
+
+// Configure the HTTP request pipeline.
+if (app.Environment.IsDevelopment())
+{
+ app.UseSwagger();
+ app.UseSwaggerUI();
+}
+
+app.UseHttpsRedirection();
+
+app.UseAuthorization();
+
+app.MapControllers();
+
+app.Run();
diff --git a/ChatGemini/Properties/launchSettings.json b/ChatGemini/Properties/launchSettings.json
new file mode 100644
index 0000000..c3e5f44
--- /dev/null
+++ b/ChatGemini/Properties/launchSettings.json
@@ -0,0 +1,41 @@
+{
+ "$schema": "http://json.schemastore.org/launchsettings.json",
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:21434",
+ "sslPort": 0
+ }
+ },
+ "profiles": {
+ "http": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "launchUrl": "swagger",
+ "applicationUrl": "http://localhost:5004",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "https": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "launchUrl": "swagger",
+ "applicationUrl": "https://localhost:7238;http://localhost:5004",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "launchUrl": "swagger",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/ChatGemini/Services/GeminiChatService.cs b/ChatGemini/Services/GeminiChatService.cs
new file mode 100644
index 0000000..e25e7b3
--- /dev/null
+++ b/ChatGemini/Services/GeminiChatService.cs
@@ -0,0 +1,108 @@
+using ChatServerSpace.Models;
+using Microsoft.SemanticKernel;
+using Microsoft.SemanticKernel.ChatCompletion;
+using Microsoft.SemanticKernel.Connectors.Google;
+
+#pragma warning disable SKEXP0070 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
+namespace ChatServerSpace.Services
+{
+ public class GeminiChatService : IChatService
+ {
+ private readonly IChatHistoryService _historyService;
+ private readonly Kernel _kernel;
+ private readonly ILogger _logger;
+
+ public GeminiChatService(IChatHistoryService historyService, IConfiguration config, ILogger logger)
+ {
+ _historyService = historyService;
+ _logger = logger;
+
+ var apiKey = config["Google:GeminiApiKey"] ?? throw new ArgumentNullException("Google:GeminiApiKey configuration is missing");
+ var modelId = config["Google:ModelId"] ?? "gemini-1.5-pro";
+
+ _kernel = Kernel.CreateBuilder()
+ .AddGoogleAIGeminiChatCompletion(modelId, apiKey)
+ .Build();
+ }
+
+ public async Task ProcessMessageAsync(ChatRequest request)
+ {
+ try
+ {
+ // Save user message to history
+ var userMessage = new ChatMessage
+ {
+
+ SessionId = request.SessionId,
+ Role = "user",
+ Content = request.Message
+ };
+ await _historyService.SaveMessageAsync(userMessage);
+
+ // Get chat history
+ var history = await _historyService.GetSessionHistoryAsync(request.SessionId);
+
+ // Create chat history for Semantic Kernel
+ var chatHistory = new Microsoft.SemanticKernel.ChatCompletion.ChatHistory();
+
+ foreach (var message in history)
+ {
+ if (message.Role.Equals("user", StringComparison.OrdinalIgnoreCase))
+ {
+ chatHistory.AddUserMessage(message.Content);
+ }
+ else if (message.Role.Equals("assistant", StringComparison.OrdinalIgnoreCase))
+ {
+ chatHistory.AddAssistantMessage(message.Content);
+ }
+ }
+
+ try
+ {
+ // Get response from Gemini
+ var chatCompletionService = _kernel.GetRequiredService();
+
+ var exec = new PromptExecutionSettings
+ {
+ ExtensionData = new Dictionary
+ {
+ { "maxOutputTokens", 8192 },
+ { "temperature", 0.7 },
+ { "topP", 0.95 },
+ { "stopSequences", new List() }
+ }
+ };
+ var result = await chatCompletionService.GetChatMessageContentAsync(chatHistory, exec);
+ var responseText = result.ToString();
+
+ // Save assistant message to history
+ var assistantMessage = new ChatMessage
+ {
+ SessionId = request.SessionId,
+ Role = "assistant",
+ Content = responseText
+ };
+ await _historyService.SaveMessageAsync(assistantMessage);
+
+ await Task.Delay(2000);
+
+ return new ChatResponse
+ {
+ SessionId = request.SessionId,
+ Response = responseText
+ };
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error getting response from Gemini");
+ throw;
+ }
+ }
+ catch (Exception ex)
+ {
+ throw new Exception("Erro na parada!", ex);
+ }
+ }
+ }
+}
+#pragma warning restore SKEXP0070 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
diff --git a/ChatGemini/Services/IChatHistoryService.cs b/ChatGemini/Services/IChatHistoryService.cs
new file mode 100644
index 0000000..5d7ee7a
--- /dev/null
+++ b/ChatGemini/Services/IChatHistoryService.cs
@@ -0,0 +1,10 @@
+using ChatServerSpace.Models;
+
+namespace ChatServerSpace.Services
+{
+ public interface IChatHistoryService
+ {
+ Task SaveMessageAsync(ChatMessage message);
+ Task> GetSessionHistoryAsync(string sessionId);
+ }
+}
diff --git a/ChatGemini/Services/IChatService.cs b/ChatGemini/Services/IChatService.cs
new file mode 100644
index 0000000..7299938
--- /dev/null
+++ b/ChatGemini/Services/IChatService.cs
@@ -0,0 +1,9 @@
+using ChatServerSpace.Models;
+
+namespace ChatServerSpace.Services
+{
+ public interface IChatService
+ {
+ Task ProcessMessageAsync(ChatRequest request);
+ }
+}
diff --git a/ChatGemini/Services/MongoDbChatHistoryService.cs b/ChatGemini/Services/MongoDbChatHistoryService.cs
new file mode 100644
index 0000000..f2e02fd
--- /dev/null
+++ b/ChatGemini/Services/MongoDbChatHistoryService.cs
@@ -0,0 +1,36 @@
+using ChatServerSpace.Models;
+using MongoDB.Driver;
+
+namespace ChatServerSpace.Services
+{
+ public class MongoDbChatHistoryService : IChatHistoryService
+ {
+ private readonly IMongoCollection _messages;
+
+ public MongoDbChatHistoryService(IConfiguration config)
+ {
+ var connectionString = config["MongoDB:ConnectionString"];
+ var databaseName = config["MongoDB:DatabaseName"];
+ var collectionName = config["MongoDB:CollectionName"];
+
+ var client = new MongoClient(connectionString);
+ var database = client.GetDatabase(databaseName);
+ _messages = database.GetCollection(collectionName);
+ }
+
+ public async Task SaveMessageAsync(ChatMessage message)
+ {
+ await _messages.InsertOneAsync(message);
+ }
+
+ public async Task> GetSessionHistoryAsync(string sessionId)
+ {
+ var filter = Builders.Filter.Eq(m => m.SessionId, sessionId);
+ var sort = Builders.Sort.Ascending(m => m.Timestamp);
+
+ return await _messages.Find(filter)
+ .Sort(sort)
+ .ToListAsync();
+ }
+ }
+}
diff --git a/ChatGemini/Services/ServerSpaceChatService.cs b/ChatGemini/Services/ServerSpaceChatService.cs
new file mode 100644
index 0000000..c6263d6
--- /dev/null
+++ b/ChatGemini/Services/ServerSpaceChatService.cs
@@ -0,0 +1,120 @@
+using ChatServerSpace.Models;
+using System.Net.Http.Headers;
+using System.Text;
+using System.Text.Json;
+
+namespace ChatServerSpace.Services
+{
+ public class ServerSpaceChatService : IChatService
+ {
+ private readonly IChatHistoryService _historyService;
+ private readonly HttpClient _httpClient;
+ private readonly ILogger _logger;
+ private readonly string _apiKey;
+ private readonly JsonSerializerOptions _jsonOptions;
+
+ public ServerSpaceChatService(IChatHistoryService historyService, IConfiguration config, ILogger logger, HttpClient httpClient)
+ {
+ _historyService = historyService;
+ _logger = logger;
+ _httpClient = httpClient;
+
+ _apiKey = config["ServerSpace:ApiKey"] ?? throw new ArgumentNullException("ServerSpace:ApiKey configuration is missing");
+ _httpClient.BaseAddress = new Uri("https://gpt.serverspace.com.br/");
+ _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
+ _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _apiKey);
+
+ _jsonOptions = new JsonSerializerOptions
+ {
+ PropertyNamingPolicy = JsonNamingPolicy.CamelCase
+ };
+ }
+
+ public async Task ProcessMessageAsync(ChatRequest request)
+ {
+ try
+ {
+ // Save user message to history
+ var userMessage = new ChatMessage
+ {
+ SessionId = request.SessionId,
+ Role = "user",
+ Content = request.Message
+ };
+ await _historyService.SaveMessageAsync(userMessage);
+
+ // Get chat history
+ var history = await _historyService.GetSessionHistoryAsync(request.SessionId);
+
+ // Create messages array for API request
+ var messages = history.Select(m => new
+ {
+ role = m.Role,
+ content = m.Content
+ }).ToList();
+
+ // Create API request body
+ var requestBody = new
+ {
+ model = "anthropic/claude-3.5-haiku",
+ max_tokens = 1024,
+ top_p = 0.1,
+ temperature = 0.6,
+ messages
+ };
+
+ // Send request to ServerSpace API
+ var jsonContent = JsonSerializer.Serialize(requestBody, _jsonOptions);
+ var content = new StringContent(jsonContent, Encoding.UTF8, "application/json");
+
+ var response = await _httpClient.PostAsync("v1/chat/completions", content);
+ response.EnsureSuccessStatusCode();
+
+ var responseJson = await response.Content.ReadAsStringAsync();
+ var responseObj = JsonSerializer.Deserialize(responseJson, _jsonOptions);
+
+ if (responseObj == null || string.IsNullOrEmpty(responseObj.Choices?[0]?.Message?.Content))
+ {
+ throw new Exception("Invalid response from ServerSpace API");
+ }
+
+ var responseText = responseObj.Choices[0].Message.Content;
+
+ // Save assistant message to history
+ var assistantMessage = new ChatMessage
+ {
+ SessionId = request.SessionId,
+ Role = "assistant",
+ Content = responseText
+ };
+ await _historyService.SaveMessageAsync(assistantMessage);
+
+ return new ChatResponse
+ {
+ SessionId = request.SessionId,
+ Response = responseText
+ };
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error processing message with ServerSpace API");
+ throw;
+ }
+ }
+
+ private class ServerSpaceResponse
+ {
+ public List? Choices { get; set; }
+ }
+
+ private class ServerSpaceChoice
+ {
+ public ServerSpaceMessage? Message { get; set; }
+ }
+
+ private class ServerSpaceMessage
+ {
+ public string? Content { get; set; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ChatGemini/appsettings.Development.json b/ChatGemini/appsettings.Development.json
new file mode 100644
index 0000000..0c208ae
--- /dev/null
+++ b/ChatGemini/appsettings.Development.json
@@ -0,0 +1,8 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ }
+}
diff --git a/ChatGemini/appsettings.json b/ChatGemini/appsettings.json
new file mode 100644
index 0000000..2436180
--- /dev/null
+++ b/ChatGemini/appsettings.json
@@ -0,0 +1,21 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ },
+ "AllowedHosts": "*",
+ "Google": {
+ "GeminiApiKey": "AIzaSyBnea0la9S-rEVBv8qUqbrv37Zl9-0kHpQ",
+ "ModelId": "gemini-1.5-pro"
+ },
+ "ServerSpace": {
+ "ApiKey": "tIAXVf3AkCkkpSX+PjFvktfEeSPyA1ZYam50UO3ye/qmxVZX6PIXstmJsLZXkQ39C33onFD/81mdxvhbGHm7tQ=="
+ },
+ "MongoDB": {
+ "ConnectionString": "mongodb://admin:c4rn31r0@192.168.0.82:27017,192.168.0.81:27017/?authSource=admin",
+ "DatabaseName": "ChatServerSpaceDb",
+ "CollectionName": "ChatMessages"
+ }
+}
diff --git a/ChatServerSpace.sln b/ChatServerSpace.sln
new file mode 100644
index 0000000..12c06ba
--- /dev/null
+++ b/ChatServerSpace.sln
@@ -0,0 +1,24 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.8.34511.84
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ChatDeepInfra", "ChatServerSpace\ChatDeepInfra.csproj", "{9CC710C3-37FE-4B1A-9C6A-D01EA7A74AB7}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {9CC710C3-37FE-4B1A-9C6A-D01EA7A74AB7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9CC710C3-37FE-4B1A-9C6A-D01EA7A74AB7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9CC710C3-37FE-4B1A-9C6A-D01EA7A74AB7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9CC710C3-37FE-4B1A-9C6A-D01EA7A74AB7}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {5AF01BE8-CB55-4F4F-90FC-DDF2A1C86A09}
+ EndGlobalSection
+EndGlobal
diff --git a/ChatServerSpace/ChatDeepInfra.csproj b/ChatServerSpace/ChatDeepInfra.csproj
new file mode 100644
index 0000000..d748ec8
--- /dev/null
+++ b/ChatServerSpace/ChatDeepInfra.csproj
@@ -0,0 +1,18 @@
+
+
+
+ net8.0
+ enable
+ enable
+ ChatServerSpace
+ ChatServerSpace
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ChatServerSpace/ChatGemini.http b/ChatServerSpace/ChatGemini.http
new file mode 100644
index 0000000..29dacad
--- /dev/null
+++ b/ChatServerSpace/ChatGemini.http
@@ -0,0 +1,6 @@
+@ChatGemini_HostAddress = http://localhost:5004
+
+GET {{ChatGemini_HostAddress}}/weatherforecast/
+Accept: application/json
+
+###
diff --git a/ChatServerSpace/Controllers/ChatController.cs b/ChatServerSpace/Controllers/ChatController.cs
new file mode 100644
index 0000000..8d50e2a
--- /dev/null
+++ b/ChatServerSpace/Controllers/ChatController.cs
@@ -0,0 +1,47 @@
+using ChatServerSpace.Models;
+using ChatServerSpace.Services;
+using Microsoft.AspNetCore.Mvc;
+
+namespace ChatServerSpace.Controllers
+{
+ [ApiController]
+ [Route("api/[controller]")]
+ public class ChatController : ControllerBase
+ {
+ private readonly IChatServiceFactory _chatServiceFactory;
+ private readonly IChatService _chatService;
+ private readonly ILogger _logger;
+
+ public ChatController(IChatServiceFactory chatServiceFactory, ILogger logger)
+ {
+ _chatServiceFactory = chatServiceFactory;
+ _logger = logger;
+ }
+
+ [HttpPost]
+ public async Task> Chat([FromBody] ChatRequest request)
+ {
+ if (string.IsNullOrWhiteSpace(request.SessionId))
+ {
+ return BadRequest("SessionId is required");
+ }
+
+ if (string.IsNullOrWhiteSpace(request.Message))
+ {
+ return BadRequest("Message is required");
+ }
+
+ try
+ {
+ var chatService = _chatServiceFactory.CreateChatService();
+ var response = await chatService.ProcessMessageAsync(request);
+ return Ok(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error processing chat message");
+ return StatusCode(500, "An error occurred while processing your message");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ChatServerSpace/Models/ChatMessage.cs b/ChatServerSpace/Models/ChatMessage.cs
new file mode 100644
index 0000000..cb45bf9
--- /dev/null
+++ b/ChatServerSpace/Models/ChatMessage.cs
@@ -0,0 +1,18 @@
+using MongoDB.Bson.Serialization.Attributes;
+using MongoDB.Bson;
+using ThirdParty.Json.LitJson;
+
+namespace ChatServerSpace.Models
+{
+ public class ChatMessage
+ {
+ [BsonElement("_id")]
+ [BsonId]
+ [BsonRepresentation(BsonType.ObjectId)]
+ public string? Id { get; set; }
+ public string SessionId { get; set; } = string.Empty;
+ public string Role { get; set; } = string.Empty;
+ public string Content { get; set; } = string.Empty;
+ public DateTime Timestamp { get; set; } = DateTime.UtcNow;
+ }
+}
diff --git a/ChatServerSpace/Models/ChatRequest.cs b/ChatServerSpace/Models/ChatRequest.cs
new file mode 100644
index 0000000..175d9f3
--- /dev/null
+++ b/ChatServerSpace/Models/ChatRequest.cs
@@ -0,0 +1,9 @@
+namespace ChatServerSpace.Models
+{
+ public class ChatRequest
+ {
+ public required string SessionId { get; set; }
+ public required string Message { get; set; }
+ public required string Criativity { get; set; }
+ }
+}
diff --git a/ChatServerSpace/Models/ChatResponse.cs b/ChatServerSpace/Models/ChatResponse.cs
new file mode 100644
index 0000000..c9c470d
--- /dev/null
+++ b/ChatServerSpace/Models/ChatResponse.cs
@@ -0,0 +1,8 @@
+namespace ChatServerSpace.Models
+{
+ public class ChatResponse
+ {
+ public required string SessionId { get; set; }
+ public required string Response { get; set; }
+ }
+}
diff --git a/ChatServerSpace/Program.cs b/ChatServerSpace/Program.cs
new file mode 100644
index 0000000..98b62a2
--- /dev/null
+++ b/ChatServerSpace/Program.cs
@@ -0,0 +1,40 @@
+using ChatServerSpace.Services;
+using Microsoft.SemanticKernel;
+
+var builder = WebApplication.CreateBuilder(args);
+
+// Add services to the container.
+builder.Services.AddControllers();
+builder.Services.AddEndpointsApiExplorer();
+builder.Services.AddSwaggerGen();
+builder.Services.AddHttpClient();
+
+builder.Services.AddHttpClient()
+ .ConfigureHttpClient(client =>
+ {
+ // Aumentar o timeout para 10 minutos (600 segundos)
+ client.Timeout = TimeSpan.FromSeconds(600);
+ });
+
+// Register services
+builder.Services.AddSingleton();
+builder.Services.AddScoped();
+builder.Services.AddScoped();
+builder.Services.AddScoped();
+
+var app = builder.Build();
+
+// Configure the HTTP request pipeline.
+if (app.Environment.IsDevelopment())
+{
+ app.UseSwagger();
+ app.UseSwaggerUI();
+}
+
+app.UseHttpsRedirection();
+
+app.UseAuthorization();
+
+app.MapControllers();
+
+app.Run();
diff --git a/ChatServerSpace/Properties/launchSettings.json b/ChatServerSpace/Properties/launchSettings.json
new file mode 100644
index 0000000..c3e5f44
--- /dev/null
+++ b/ChatServerSpace/Properties/launchSettings.json
@@ -0,0 +1,41 @@
+{
+ "$schema": "http://json.schemastore.org/launchsettings.json",
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:21434",
+ "sslPort": 0
+ }
+ },
+ "profiles": {
+ "http": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "launchUrl": "swagger",
+ "applicationUrl": "http://localhost:5004",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "https": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "launchUrl": "swagger",
+ "applicationUrl": "https://localhost:7238;http://localhost:5004",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "launchUrl": "swagger",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/ChatServerSpace/Services/ChatServiceFactory.cs b/ChatServerSpace/Services/ChatServiceFactory.cs
new file mode 100644
index 0000000..9f56fa8
--- /dev/null
+++ b/ChatServerSpace/Services/ChatServiceFactory.cs
@@ -0,0 +1,29 @@
+namespace ChatServerSpace.Services
+{
+ public class ChatServiceFactory : IChatServiceFactory
+ {
+ private readonly IServiceProvider _serviceProvider;
+ private readonly IConfiguration _configuration;
+
+ public ChatServiceFactory(IServiceProvider serviceProvider, IConfiguration configuration)
+ {
+ _serviceProvider = serviceProvider;
+ _configuration = configuration;
+ }
+
+ public IChatService CreateChatService()
+ {
+ // Determine qual implementação usar com base nas configurações
+ var useDirectHttpClient = _configuration.GetValue("ChatServer:UseServer");
+
+ if (useDirectHttpClient== "DeepInfra")
+ {
+ return _serviceProvider.GetRequiredService();
+ }
+ else
+ {
+ return _serviceProvider.GetRequiredService();
+ }
+ }
+ }
+}
diff --git a/ChatServerSpace/Services/DeepInfraChatService.cs b/ChatServerSpace/Services/DeepInfraChatService.cs
new file mode 100644
index 0000000..fc8da67
--- /dev/null
+++ b/ChatServerSpace/Services/DeepInfraChatService.cs
@@ -0,0 +1,130 @@
+using ChatServerSpace.Models;
+using System.Net.Http.Headers;
+using System.Text;
+using System.Text.Json;
+
+namespace ChatServerSpace.Services
+{
+ public class DeepInfraChatService : IChatService
+ {
+ private readonly IChatHistoryService _historyService;
+ private readonly HttpClient _httpClient;
+ private readonly ILogger _logger;
+ private readonly string _apiKey;
+ private readonly string _modelId;
+ private readonly string _endpoint;
+
+ public DeepInfraChatService(
+ IChatHistoryService historyService,
+ IConfiguration config,
+ ILogger logger,
+ HttpClient httpClient)
+ {
+ _historyService = historyService;
+ _logger = logger;
+ _httpClient = httpClient;
+
+ _apiKey = config["ChatServer:ApiKey"] ?? throw new ArgumentNullException("ServeSpace:ApiKey configuration is missing");
+ _modelId = config["ChatServer:ModelId"] ?? "meta-llama/Meta-Llama-3.1-70B-Instruct";
+ _endpoint = config["ChatServer:Url"] ?? "https://api.deepinfra.com/v1/openai/chat/completions";
+
+ // Configurar o cliente HTTP
+ _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _apiKey);
+ _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
+ }
+
+ public async Task ProcessMessageAsync(ChatRequest request)
+ {
+ try
+ {
+ // Salvar mensagem do usuário no histórico
+ var userMessage = new ChatMessage
+ {
+ SessionId = request.SessionId,
+ Role = "user",
+ Content = request.Message
+ };
+ await _historyService.SaveMessageAsync(userMessage);
+
+ // Obter histórico de chat
+ var history = await _historyService.GetSessionHistoryAsync(request.SessionId);
+
+ // Criar mensagens para a API
+ var messages = history.Select(m => new
+ {
+ role = m.Role.ToLowerInvariant(),
+ content = m.Content
+ }).ToList();
+
+ // Criando o payload para a requisição
+ var payload = new
+ {
+ model = _modelId,
+ messages,
+ max_tokens = 8192,
+ temperature = 0.8,
+ top_p = 0.95
+ };
+
+ _logger.LogInformation("Enviando solicitação para a API DeepInfra: {0}", JsonSerializer.Serialize(payload));
+
+ // Enviando requisição para a API
+ var content = new StringContent(
+ JsonSerializer.Serialize(payload),
+ Encoding.UTF8,
+ "application/json");
+
+ _httpClient.Timeout = TimeSpan.FromSeconds(600);
+ var response = await _httpClient.PostAsync(_endpoint, content);
+
+ // Garantir que a resposta foi bem-sucedida
+ response.EnsureSuccessStatusCode();
+
+ // Processar resposta
+ var responseContent = await response.Content.ReadAsStringAsync();
+ _logger.LogInformation("Resposta recebida da API: {0}", responseContent);
+
+ var apiResponse = JsonSerializer.Deserialize(responseContent,
+ new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
+
+ var responseText = apiResponse?.Choices?.FirstOrDefault()?.Message?.Content ?? "Sem resposta";
+
+ // Salvar resposta do assistente no histórico
+ var assistantMessage = new ChatMessage
+ {
+ SessionId = request.SessionId,
+ Role = "assistant",
+ Content = responseText
+ };
+ await _historyService.SaveMessageAsync(assistantMessage);
+
+ return new ChatResponse
+ {
+ SessionId = request.SessionId,
+ Response = responseText
+ };
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Erro ao processar mensagem com DeepInfra API");
+ throw new Exception("Erro ao se comunicar com a API DeepInfra", ex);
+ }
+ }
+
+ // Classes para deserialização da resposta da API
+ private class DeepInfraResponse
+ {
+ public List? Choices { get; set; }
+ }
+
+ private class DeepInfraChoice
+ {
+ public DeepInfraMessage? Message { get; set; }
+ }
+
+ private class DeepInfraMessage
+ {
+ public string? Content { get; set; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ChatServerSpace/Services/IChatHistoryService.cs b/ChatServerSpace/Services/IChatHistoryService.cs
new file mode 100644
index 0000000..5d7ee7a
--- /dev/null
+++ b/ChatServerSpace/Services/IChatHistoryService.cs
@@ -0,0 +1,10 @@
+using ChatServerSpace.Models;
+
+namespace ChatServerSpace.Services
+{
+ public interface IChatHistoryService
+ {
+ Task SaveMessageAsync(ChatMessage message);
+ Task> GetSessionHistoryAsync(string sessionId);
+ }
+}
diff --git a/ChatServerSpace/Services/IChatService.cs b/ChatServerSpace/Services/IChatService.cs
new file mode 100644
index 0000000..7299938
--- /dev/null
+++ b/ChatServerSpace/Services/IChatService.cs
@@ -0,0 +1,9 @@
+using ChatServerSpace.Models;
+
+namespace ChatServerSpace.Services
+{
+ public interface IChatService
+ {
+ Task ProcessMessageAsync(ChatRequest request);
+ }
+}
diff --git a/ChatServerSpace/Services/IChatServiceFactory.cs b/ChatServerSpace/Services/IChatServiceFactory.cs
new file mode 100644
index 0000000..cc4ed65
--- /dev/null
+++ b/ChatServerSpace/Services/IChatServiceFactory.cs
@@ -0,0 +1,7 @@
+namespace ChatServerSpace.Services
+{
+ public interface IChatServiceFactory
+ {
+ IChatService CreateChatService();
+ }
+}
diff --git a/ChatServerSpace/Services/MongoDbChatHistoryService.cs b/ChatServerSpace/Services/MongoDbChatHistoryService.cs
new file mode 100644
index 0000000..f2e02fd
--- /dev/null
+++ b/ChatServerSpace/Services/MongoDbChatHistoryService.cs
@@ -0,0 +1,36 @@
+using ChatServerSpace.Models;
+using MongoDB.Driver;
+
+namespace ChatServerSpace.Services
+{
+ public class MongoDbChatHistoryService : IChatHistoryService
+ {
+ private readonly IMongoCollection _messages;
+
+ public MongoDbChatHistoryService(IConfiguration config)
+ {
+ var connectionString = config["MongoDB:ConnectionString"];
+ var databaseName = config["MongoDB:DatabaseName"];
+ var collectionName = config["MongoDB:CollectionName"];
+
+ var client = new MongoClient(connectionString);
+ var database = client.GetDatabase(databaseName);
+ _messages = database.GetCollection(collectionName);
+ }
+
+ public async Task SaveMessageAsync(ChatMessage message)
+ {
+ await _messages.InsertOneAsync(message);
+ }
+
+ public async Task> GetSessionHistoryAsync(string sessionId)
+ {
+ var filter = Builders.Filter.Eq(m => m.SessionId, sessionId);
+ var sort = Builders.Sort.Ascending(m => m.Timestamp);
+
+ return await _messages.Find(filter)
+ .Sort(sort)
+ .ToListAsync();
+ }
+ }
+}
diff --git a/ChatServerSpace/Services/ServerSpaceChatService.cs b/ChatServerSpace/Services/ServerSpaceChatService.cs
new file mode 100644
index 0000000..5db3e93
--- /dev/null
+++ b/ChatServerSpace/Services/ServerSpaceChatService.cs
@@ -0,0 +1,126 @@
+using ChatServerSpace.Models;
+using Microsoft.AspNetCore.DataProtection.KeyManagement;
+using Microsoft.SemanticKernel;
+using Microsoft.SemanticKernel.ChatCompletion;
+using System.Net.Http.Headers;
+using System.Text;
+using System.Text.Json;
+
+namespace ChatServerSpace.Services
+{
+ public class ServerSpaceChatService : IChatService
+ {
+ private readonly IChatHistoryService _historyService;
+ private readonly Kernel _kernel;
+ private readonly ILogger _logger;
+
+ public ServerSpaceChatService(IChatHistoryService historyService, IConfiguration config, ILogger logger, HttpClient httpClient)
+ {
+ _historyService = historyService;
+ _logger = logger;
+
+ var apiKey = config["ChatServer:ApiKey"] ?? throw new ArgumentNullException("ServeSpace:ApiKey configuration is missing");
+ var modelId = config["ChatServer:ModelId"] ?? "anthropic/claude-3.7-sonnet";
+ var endpoint = config["ChatServer:Url"] ?? "https://api.deepinfra.com/v1/openai/chat/completions";
+
+
+ _kernel = Kernel.CreateBuilder()
+ .AddOpenAIChatCompletion(modelId, new Uri(endpoint), apiKey)
+ .Build();
+ }
+
+ public async Task ProcessMessageAsync(ChatRequest request)
+ {
+ try
+ {
+ // Save user message to history
+ var userMessage = new ChatMessage
+ {
+
+ SessionId = request.SessionId,
+ Role = "user",
+ Content = request.Message
+ };
+ await _historyService.SaveMessageAsync(userMessage);
+
+ // Get chat history
+ var history = await _historyService.GetSessionHistoryAsync(request.SessionId);
+
+ // Create chat history for Semantic Kernel
+ var chatHistory = new Microsoft.SemanticKernel.ChatCompletion.ChatHistory();
+
+ foreach (var message in history)
+ {
+ if (message.Role.Equals("user", StringComparison.OrdinalIgnoreCase))
+ {
+ chatHistory.AddUserMessage(message.Content);
+ }
+ else if (message.Role.Equals("assistant", StringComparison.OrdinalIgnoreCase))
+ {
+ chatHistory.AddAssistantMessage(message.Content);
+ }
+ }
+
+ try
+ {
+ // Get response from Gemini
+ var chatCompletionService = _kernel.GetRequiredService();
+
+ var exec = new PromptExecutionSettings
+ {
+ ExtensionData = new Dictionary
+ {
+ { "maxOutputTokens", 8192 },
+ { "temperature", 0.8 },
+ { "topP", 0.95 },
+ //{ "stopSequences", new List() }
+ }
+ };
+ var result = await chatCompletionService.GetChatMessageContentAsync(chatHistory, exec);
+ var responseText = result.ToString();
+
+ // Save assistant message to history
+ var assistantMessage = new ChatMessage
+ {
+ SessionId = request.SessionId,
+ Role = "assistant",
+ Content = responseText
+ };
+ await _historyService.SaveMessageAsync(assistantMessage);
+
+ await Task.Delay(2000);
+
+ return new ChatResponse
+ {
+ SessionId = request.SessionId,
+ Response = responseText
+ };
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error getting response from Gemini");
+ throw;
+ }
+ }
+ catch (Exception ex)
+ {
+ throw new Exception("Erro na parada!", ex);
+ }
+ }
+
+ private class ServerSpaceResponse
+ {
+ public List? Choices { get; set; }
+ }
+
+ private class ServerSpaceChoice
+ {
+ public ServerSpaceMessage? Message { get; set; }
+ }
+
+ private class ServerSpaceMessage
+ {
+ public string? Content { get; set; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ChatServerSpace/appsettings.Development.json b/ChatServerSpace/appsettings.Development.json
new file mode 100644
index 0000000..0c208ae
--- /dev/null
+++ b/ChatServerSpace/appsettings.Development.json
@@ -0,0 +1,8 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ }
+}
diff --git a/ChatServerSpace/appsettings.json b/ChatServerSpace/appsettings.json
new file mode 100644
index 0000000..e801f3f
--- /dev/null
+++ b/ChatServerSpace/appsettings.json
@@ -0,0 +1,23 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ },
+ "AllowedHosts": "*",
+ "ChatServer": {
+ //"ApiKey": "tIAXVf3AkCkkpSX+PjFvktfEeSPyA1ZYam50UO3ye/qmxVZX6PIXstmJsLZXkQ39C33onFD/81mdxvhbGHm7tQ==",
+ //"ModelId": "anthropic/claude-3.5-haiku",
+ //"Url": "https://gpt.serverspace.com.br/v1/chat/completions"
+ "ApiKey": "HedaR4yPrp9N2XSHfwdZjpZvPIxejPFK",
+ "ModelId": "meta-llama/Meta-Llama-3.1-70B-Instruct",
+ "Url": "https://api.deepinfra.com/v1/openai/chat/completions",
+ "UseServer": "DeepInfra"
+ },
+ "MongoDB": {
+ "ConnectionString": "mongodb://admin:c4rn31r0@192.168.0.82:27017,192.168.0.81:27017/?authSource=admin",
+ "DatabaseName": "ChatServerSpaceDb",
+ "CollectionName": "ChatMessages"
+ }
+}