This commit is contained in:
mmrbnjd
2025-08-28 14:56:41 +03:30
parent 6bb19f9d8b
commit 564429be01
9 changed files with 360 additions and 20 deletions

View File

@@ -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 {

View File

@@ -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; }
}
}

View File

@@ -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<aiSetting> aiSettings)
public LocalopenAI(IOptions<aiSetting> aiSettings)
{
_aiSettings = aiSettings.Value;
}
@@ -31,7 +31,7 @@ namespace Hushian.Infrastructure
var content = new
{
model = model,
model,
messages = new[]
{
new { role = "system", content = "شما یک دستیار پاسخگو به سوالات هستید." },

View File

@@ -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<aigrpcserver> aigrpc, IOptions<aiSetting> aiSettings)
{
_aigrpc = aigrpc.Value;
_aiSettings = aiSettings.Value;
}
public async Task<ResponseBase<string>> SendQuestion(aiRequestModel Request)
{
var Response = new ResponseBase<string>();
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;
}
}
}

View File

@@ -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<aiSetting>(configuration.GetSection("aiSettings"));
services.Configure<aigrpcserver>(configuration.GetSection("aigrpcserver"));
services.AddTransient<Iaiass, openAI>();
services.AddScoped(c => new Melipayamak.RestClient(configuration.GetSection("MessageSettings:UserName").Value, configuration.GetSection("MessageSettings:Password").Value));

View File

@@ -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 {
}
}
/// <summary>Field number for the "model" field.</summary>
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");
}
}
/// <summary>Field number for the "apitoken" field.</summary>
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");
}
}
/// <summary>Field number for the "url" field.</summary>
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;
}
}
}
}

View File

@@ -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<aiaReply> SendQuestion(aiaRequest request, ServerCallContext context)
public async override Task<aiaReply> 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}"
};
}
}

View File

@@ -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 {
}
}
/// <summary>Field number for the "model" field.</summary>
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");
}
}
/// <summary>Field number for the "apitoken" field.</summary>
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");
}
}
/// <summary>Field number for the "url" field.</summary>
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;
}
}
}
}

View File

@@ -16,6 +16,11 @@
"url": "https://api.openai.com/v1/chat/completions",
"apitoken": "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"
},
"aigrpcserver": {
"target": "localhost:5010"
},
"Logging": {
"LogLevel": {