From 564429be0119bf5d9f8a0b93272c18ae11e5c044 Mon Sep 17 00:00:00 2001 From: mmrbnjd Date: Thu, 28 Aug 2025 14:56:41 +0330 Subject: [PATCH] ... --- Common/Protos/aia.proto | 3 + .../Models/aia/aiSetting - Copy.cs | 13 ++ .../{openAI.cs => Ai_Ass/LocalOpenAI.cs} | 8 +- .../Infrastructure/Ai_Ass/OpenAI .cs | 65 +++++++++ .../InfrastractureServicesRegistration.cs | 2 + Infrastructure/Infrastructure/models/Aia.cs | 124 +++++++++++++++++- .../AIAss/Services/aiAssistanceService.cs | 36 ++++- Presentation/AIAss/models/Aia.cs | 124 +++++++++++++++++- Presentation/Hushian.WebApi/appsettings.json | 5 + 9 files changed, 360 insertions(+), 20 deletions(-) create mode 100644 Hushian.Application/Models/aia/aiSetting - Copy.cs rename Infrastructure/Infrastructure/{openAI.cs => Ai_Ass/LocalOpenAI.cs} (93%) create mode 100644 Infrastructure/Infrastructure/Ai_Ass/OpenAI .cs diff --git a/Common/Protos/aia.proto b/Common/Protos/aia.proto index bd37321..e754987 100644 --- a/Common/Protos/aia.proto +++ b/Common/Protos/aia.proto @@ -12,6 +12,9 @@ service aiAssistance { message aiaRequest { string question = 1; string prompts = 2; + string model = 3; + string apitoken = 4; + string url = 5; } message aiaReply { diff --git a/Hushian.Application/Models/aia/aiSetting - Copy.cs b/Hushian.Application/Models/aia/aiSetting - Copy.cs new file mode 100644 index 0000000..5c9c2c5 --- /dev/null +++ b/Hushian.Application/Models/aia/aiSetting - Copy.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Hushian.Application.Models.aia +{ + public class aigrpcserver + { + public string target { get; set; } + } +} diff --git a/Infrastructure/Infrastructure/openAI.cs b/Infrastructure/Infrastructure/Ai_Ass/LocalOpenAI.cs similarity index 93% rename from Infrastructure/Infrastructure/openAI.cs rename to Infrastructure/Infrastructure/Ai_Ass/LocalOpenAI.cs index 83dc5cd..9133d98 100644 --- a/Infrastructure/Infrastructure/openAI.cs +++ b/Infrastructure/Infrastructure/Ai_Ass/LocalOpenAI.cs @@ -10,13 +10,13 @@ using System.Text; using System.Text.Json; using System.Threading.Tasks; -namespace Hushian.Infrastructure +namespace Hushian.Infrastructure.Ai_Ass { - public class openAI : Iaiass + public class LocalopenAI : Iaiass { const string model = "gpt-4o-mini"; private aiSetting _aiSettings; - public openAI(IOptions aiSettings) + public LocalopenAI(IOptions aiSettings) { _aiSettings = aiSettings.Value; } @@ -31,7 +31,7 @@ namespace Hushian.Infrastructure var content = new { - model = model, + model, messages = new[] { new { role = "system", content = "شما یک دستیار پاسخگو به سوالات هستید." }, diff --git a/Infrastructure/Infrastructure/Ai_Ass/OpenAI .cs b/Infrastructure/Infrastructure/Ai_Ass/OpenAI .cs new file mode 100644 index 0000000..4231c11 --- /dev/null +++ b/Infrastructure/Infrastructure/Ai_Ass/OpenAI .cs @@ -0,0 +1,65 @@ +using AIAss.Protos; +using Grpc.Core; +using Hushian.Application.Contracts; +using Hushian.Application.Models; +using Hushian.Application.Models.aia; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http.Headers; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; + +namespace Hushian.Infrastructure.Ai_Ass +{ + public class openAI : Iaiass + { + const string model = "gpt-4o-mini"; + private aigrpcserver _aigrpc; + private aiSetting _aiSettings; + public openAI(IOptions aigrpc, IOptions aiSettings) + { + _aigrpc = aigrpc.Value; + _aiSettings = aiSettings.Value; + } + + public async Task> SendQuestion(aiRequestModel Request) + { + var Response = new ResponseBase(); + var channel = new Channel(_aigrpc.target, ChannelCredentials.Insecure); + + try + { + await channel.ConnectAsync(); + + var aiaServiceClient = new aiAssistance.aiAssistanceClient(channel); + var response= await aiaServiceClient.SendQuestionAsync + (new aiaRequest() + { Prompts = Request.ToString(), + Question = Request.question, + Model=model,Apitoken=_aiSettings.apitoken,Url=_aiSettings.url }); + + if (response!=null) + { + Response.Value = response.Message; + Response.Success = true; + } + else + { + Response.Errors.Add("خطا در ارتباط سرور ai"); + } + } + catch (Exception ex) + { + Response.Errors.Add("خطا مدیریت نشده در ارتباط سرور ai"); + } + finally + { + await channel.ShutdownAsync(); + } + return Response; + } + } +} diff --git a/Infrastructure/Infrastructure/InfrastractureServicesRegistration.cs b/Infrastructure/Infrastructure/InfrastractureServicesRegistration.cs index f34d18a..3ee5ca5 100644 --- a/Infrastructure/Infrastructure/InfrastractureServicesRegistration.cs +++ b/Infrastructure/Infrastructure/InfrastractureServicesRegistration.cs @@ -2,6 +2,7 @@ using Hushian.Application.Contracts; using Hushian.Application.Models.aia; using Hushian.Application.Models.Message; +using Hushian.Infrastructure.Ai_Ass; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; namespace Hushian.Infrastructure @@ -20,6 +21,7 @@ namespace Hushian.Infrastructure services.Configure(configuration.GetSection("aiSettings")); + services.Configure(configuration.GetSection("aigrpcserver")); services.AddTransient(); services.AddScoped(c => new Melipayamak.RestClient(configuration.GetSection("MessageSettings:UserName").Value, configuration.GetSection("MessageSettings:Password").Value)); diff --git a/Infrastructure/Infrastructure/models/Aia.cs b/Infrastructure/Infrastructure/models/Aia.cs index abc6550..96e5da8 100644 --- a/Infrastructure/Infrastructure/models/Aia.cs +++ b/Infrastructure/Infrastructure/models/Aia.cs @@ -24,15 +24,16 @@ namespace AIAss.Protos { static AiaReflection() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( - "CglhaWEucHJvdG8SA2FpYSIvCgphaWFSZXF1ZXN0EhAKCHF1ZXN0aW9uGAEg", - "ASgJEg8KB3Byb21wdHMYAiABKAkiGwoIYWlhUmVwbHkSDwoHbWVzc2FnZRgB", - "IAEoCTI+CgxhaUFzc2lzdGFuY2USLgoMU2VuZFF1ZXN0aW9uEg8uYWlhLmFp", - "YVJlcXVlc3QaDS5haWEuYWlhUmVwbHlCD6oCDEFJQXNzLlByb3Rvc2IGcHJv", - "dG8z")); + "CglhaWEucHJvdG8SA2FpYSJdCgphaWFSZXF1ZXN0EhAKCHF1ZXN0aW9uGAEg", + "ASgJEg8KB3Byb21wdHMYAiABKAkSDQoFbW9kZWwYAyABKAkSEAoIYXBpdG9r", + "ZW4YBCABKAkSCwoDdXJsGAUgASgJIhsKCGFpYVJlcGx5Eg8KB21lc3NhZ2UY", + "ASABKAkyPgoMYWlBc3Npc3RhbmNlEi4KDFNlbmRRdWVzdGlvbhIPLmFpYS5h", + "aWFSZXF1ZXN0Gg0uYWlhLmFpYVJlcGx5Qg+qAgxBSUFzcy5Qcm90b3NiBnBy", + "b3RvMw==")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::AIAss.Protos.aiaRequest), global::AIAss.Protos.aiaRequest.Parser, new[]{ "Question", "Prompts" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::AIAss.Protos.aiaRequest), global::AIAss.Protos.aiaRequest.Parser, new[]{ "Question", "Prompts", "Model", "Apitoken", "Url" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::AIAss.Protos.aiaReply), global::AIAss.Protos.aiaReply.Parser, new[]{ "Message" }, null, null, null, null) })); } @@ -77,6 +78,9 @@ namespace AIAss.Protos { public aiaRequest(aiaRequest other) : this() { question_ = other.question_; prompts_ = other.prompts_; + model_ = other.model_; + apitoken_ = other.apitoken_; + url_ = other.url_; _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } @@ -110,6 +114,42 @@ namespace AIAss.Protos { } } + /// Field number for the "model" field. + public const int ModelFieldNumber = 3; + private string model_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Model { + get { return model_; } + set { + model_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "apitoken" field. + public const int ApitokenFieldNumber = 4; + private string apitoken_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Apitoken { + get { return apitoken_; } + set { + apitoken_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "url" field. + public const int UrlFieldNumber = 5; + private string url_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Url { + get { return url_; } + set { + url_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override bool Equals(object other) { @@ -127,6 +167,9 @@ namespace AIAss.Protos { } if (Question != other.Question) return false; if (Prompts != other.Prompts) return false; + if (Model != other.Model) return false; + if (Apitoken != other.Apitoken) return false; + if (Url != other.Url) return false; return Equals(_unknownFields, other._unknownFields); } @@ -136,6 +179,9 @@ namespace AIAss.Protos { int hash = 1; if (Question.Length != 0) hash ^= Question.GetHashCode(); if (Prompts.Length != 0) hash ^= Prompts.GetHashCode(); + if (Model.Length != 0) hash ^= Model.GetHashCode(); + if (Apitoken.Length != 0) hash ^= Apitoken.GetHashCode(); + if (Url.Length != 0) hash ^= Url.GetHashCode(); if (_unknownFields != null) { hash ^= _unknownFields.GetHashCode(); } @@ -162,6 +208,18 @@ namespace AIAss.Protos { output.WriteRawTag(18); output.WriteString(Prompts); } + if (Model.Length != 0) { + output.WriteRawTag(26); + output.WriteString(Model); + } + if (Apitoken.Length != 0) { + output.WriteRawTag(34); + output.WriteString(Apitoken); + } + if (Url.Length != 0) { + output.WriteRawTag(42); + output.WriteString(Url); + } if (_unknownFields != null) { _unknownFields.WriteTo(output); } @@ -180,6 +238,18 @@ namespace AIAss.Protos { output.WriteRawTag(18); output.WriteString(Prompts); } + if (Model.Length != 0) { + output.WriteRawTag(26); + output.WriteString(Model); + } + if (Apitoken.Length != 0) { + output.WriteRawTag(34); + output.WriteString(Apitoken); + } + if (Url.Length != 0) { + output.WriteRawTag(42); + output.WriteString(Url); + } if (_unknownFields != null) { _unknownFields.WriteTo(ref output); } @@ -196,6 +266,15 @@ namespace AIAss.Protos { if (Prompts.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(Prompts); } + if (Model.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Model); + } + if (Apitoken.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Apitoken); + } + if (Url.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Url); + } if (_unknownFields != null) { size += _unknownFields.CalculateSize(); } @@ -214,6 +293,15 @@ namespace AIAss.Protos { if (other.Prompts.Length != 0) { Prompts = other.Prompts; } + if (other.Model.Length != 0) { + Model = other.Model; + } + if (other.Apitoken.Length != 0) { + Apitoken = other.Apitoken; + } + if (other.Url.Length != 0) { + Url = other.Url; + } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } @@ -237,6 +325,18 @@ namespace AIAss.Protos { Prompts = input.ReadString(); break; } + case 26: { + Model = input.ReadString(); + break; + } + case 34: { + Apitoken = input.ReadString(); + break; + } + case 42: { + Url = input.ReadString(); + break; + } } } #endif @@ -260,6 +360,18 @@ namespace AIAss.Protos { Prompts = input.ReadString(); break; } + case 26: { + Model = input.ReadString(); + break; + } + case 34: { + Apitoken = input.ReadString(); + break; + } + case 42: { + Url = input.ReadString(); + break; + } } } } diff --git a/Presentation/AIAss/Services/aiAssistanceService.cs b/Presentation/AIAss/Services/aiAssistanceService.cs index 9e66f3b..69de178 100644 --- a/Presentation/AIAss/Services/aiAssistanceService.cs +++ b/Presentation/AIAss/Services/aiAssistanceService.cs @@ -1,19 +1,47 @@ using Grpc.Core; using AIAss; using AIAss.Protos; +using System.Net.Http.Headers; +using System.Text.Json; +using System.Text; namespace AIAss.Services; public class aiAssistanceService: aiAssistance.aiAssistanceBase { - public override Task SendQuestion(aiaRequest request, ServerCallContext context) + public async override Task SendQuestion(aiaRequest request, ServerCallContext context) { - var reply = new aiaReply + using var client = new HttpClient(); + client.DefaultRequestHeaders.Authorization = + new AuthenticationHeaderValue("Bearer", request.Apitoken); + var content = new { - Message = $" {request.Question}" + model= request.Model, + messages = new[] + { + new { role = "system", content = "شما یک دستیار پاسخگو به سوالات هستید." }, + new { role = "user", content = $"با توجه به این متن:{request.Prompts}به این سوال پاسخ بده:{ request.Question}" }, + new { role = "system", content = "به سوالات غیره متن بالا پاسخ نده و بگو در این زمینه اطلاعی ندارم" } + } }; + var response = await client.PostAsync(request.Url, + new StringContent(JsonSerializer.Serialize(content), Encoding.UTF8, "application/json")); + string reponse = ""; + if (response.IsSuccessStatusCode) + { + var json = await response.Content.ReadAsStringAsync(); + using var doc = JsonDocument.Parse(json); + reponse = doc.RootElement.GetProperty("choices")[0].GetProperty("message").GetProperty("content").GetString(); + } + else + { + reponse="خطا در ارتباط سرور ai"; + } - return Task.FromResult(reply); + return new aiaReply + { + Message = $" {reponse}" + }; } } diff --git a/Presentation/AIAss/models/Aia.cs b/Presentation/AIAss/models/Aia.cs index abc6550..96e5da8 100644 --- a/Presentation/AIAss/models/Aia.cs +++ b/Presentation/AIAss/models/Aia.cs @@ -24,15 +24,16 @@ namespace AIAss.Protos { static AiaReflection() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( - "CglhaWEucHJvdG8SA2FpYSIvCgphaWFSZXF1ZXN0EhAKCHF1ZXN0aW9uGAEg", - "ASgJEg8KB3Byb21wdHMYAiABKAkiGwoIYWlhUmVwbHkSDwoHbWVzc2FnZRgB", - "IAEoCTI+CgxhaUFzc2lzdGFuY2USLgoMU2VuZFF1ZXN0aW9uEg8uYWlhLmFp", - "YVJlcXVlc3QaDS5haWEuYWlhUmVwbHlCD6oCDEFJQXNzLlByb3Rvc2IGcHJv", - "dG8z")); + "CglhaWEucHJvdG8SA2FpYSJdCgphaWFSZXF1ZXN0EhAKCHF1ZXN0aW9uGAEg", + "ASgJEg8KB3Byb21wdHMYAiABKAkSDQoFbW9kZWwYAyABKAkSEAoIYXBpdG9r", + "ZW4YBCABKAkSCwoDdXJsGAUgASgJIhsKCGFpYVJlcGx5Eg8KB21lc3NhZ2UY", + "ASABKAkyPgoMYWlBc3Npc3RhbmNlEi4KDFNlbmRRdWVzdGlvbhIPLmFpYS5h", + "aWFSZXF1ZXN0Gg0uYWlhLmFpYVJlcGx5Qg+qAgxBSUFzcy5Qcm90b3NiBnBy", + "b3RvMw==")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::AIAss.Protos.aiaRequest), global::AIAss.Protos.aiaRequest.Parser, new[]{ "Question", "Prompts" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::AIAss.Protos.aiaRequest), global::AIAss.Protos.aiaRequest.Parser, new[]{ "Question", "Prompts", "Model", "Apitoken", "Url" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::AIAss.Protos.aiaReply), global::AIAss.Protos.aiaReply.Parser, new[]{ "Message" }, null, null, null, null) })); } @@ -77,6 +78,9 @@ namespace AIAss.Protos { public aiaRequest(aiaRequest other) : this() { question_ = other.question_; prompts_ = other.prompts_; + model_ = other.model_; + apitoken_ = other.apitoken_; + url_ = other.url_; _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } @@ -110,6 +114,42 @@ namespace AIAss.Protos { } } + /// Field number for the "model" field. + public const int ModelFieldNumber = 3; + private string model_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Model { + get { return model_; } + set { + model_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "apitoken" field. + public const int ApitokenFieldNumber = 4; + private string apitoken_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Apitoken { + get { return apitoken_; } + set { + apitoken_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "url" field. + public const int UrlFieldNumber = 5; + private string url_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Url { + get { return url_; } + set { + url_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override bool Equals(object other) { @@ -127,6 +167,9 @@ namespace AIAss.Protos { } if (Question != other.Question) return false; if (Prompts != other.Prompts) return false; + if (Model != other.Model) return false; + if (Apitoken != other.Apitoken) return false; + if (Url != other.Url) return false; return Equals(_unknownFields, other._unknownFields); } @@ -136,6 +179,9 @@ namespace AIAss.Protos { int hash = 1; if (Question.Length != 0) hash ^= Question.GetHashCode(); if (Prompts.Length != 0) hash ^= Prompts.GetHashCode(); + if (Model.Length != 0) hash ^= Model.GetHashCode(); + if (Apitoken.Length != 0) hash ^= Apitoken.GetHashCode(); + if (Url.Length != 0) hash ^= Url.GetHashCode(); if (_unknownFields != null) { hash ^= _unknownFields.GetHashCode(); } @@ -162,6 +208,18 @@ namespace AIAss.Protos { output.WriteRawTag(18); output.WriteString(Prompts); } + if (Model.Length != 0) { + output.WriteRawTag(26); + output.WriteString(Model); + } + if (Apitoken.Length != 0) { + output.WriteRawTag(34); + output.WriteString(Apitoken); + } + if (Url.Length != 0) { + output.WriteRawTag(42); + output.WriteString(Url); + } if (_unknownFields != null) { _unknownFields.WriteTo(output); } @@ -180,6 +238,18 @@ namespace AIAss.Protos { output.WriteRawTag(18); output.WriteString(Prompts); } + if (Model.Length != 0) { + output.WriteRawTag(26); + output.WriteString(Model); + } + if (Apitoken.Length != 0) { + output.WriteRawTag(34); + output.WriteString(Apitoken); + } + if (Url.Length != 0) { + output.WriteRawTag(42); + output.WriteString(Url); + } if (_unknownFields != null) { _unknownFields.WriteTo(ref output); } @@ -196,6 +266,15 @@ namespace AIAss.Protos { if (Prompts.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(Prompts); } + if (Model.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Model); + } + if (Apitoken.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Apitoken); + } + if (Url.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Url); + } if (_unknownFields != null) { size += _unknownFields.CalculateSize(); } @@ -214,6 +293,15 @@ namespace AIAss.Protos { if (other.Prompts.Length != 0) { Prompts = other.Prompts; } + if (other.Model.Length != 0) { + Model = other.Model; + } + if (other.Apitoken.Length != 0) { + Apitoken = other.Apitoken; + } + if (other.Url.Length != 0) { + Url = other.Url; + } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } @@ -237,6 +325,18 @@ namespace AIAss.Protos { Prompts = input.ReadString(); break; } + case 26: { + Model = input.ReadString(); + break; + } + case 34: { + Apitoken = input.ReadString(); + break; + } + case 42: { + Url = input.ReadString(); + break; + } } } #endif @@ -260,6 +360,18 @@ namespace AIAss.Protos { Prompts = input.ReadString(); break; } + case 26: { + Model = input.ReadString(); + break; + } + case 34: { + Apitoken = input.ReadString(); + break; + } + case 42: { + Url = input.ReadString(); + break; + } } } } diff --git a/Presentation/Hushian.WebApi/appsettings.json b/Presentation/Hushian.WebApi/appsettings.json index 7c10eb1..8145fe0 100644 --- a/Presentation/Hushian.WebApi/appsettings.json +++ b/Presentation/Hushian.WebApi/appsettings.json @@ -16,6 +16,11 @@ "url": "https://api.openai.com/v1/chat/completions", "apitoken": "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" + }, + "aigrpcserver": { + "target": "localhost:5010" + + }, "Logging": { "LogLevel": {