Skip to content

Commit c86099c

Browse files
author
157
committed
Add ai knowledge base table and entity
1 parent 60d05b7 commit c86099c

9 files changed

+156
-27
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
CREATE TABLE IF NOT EXISTS number_pool(
2+
`id` INT PRIMARY KEY AUTO_INCREMENT,
3+
`number` VARCHAR(48) NOT NULL,
4+
`is_used` TINYINT(1) Default 1 NOT NULL,
5+
`created_date` DATETIME(3) NOT NULL
6+
)CHARSET=utf8mb4;
7+
8+
CREATE TABLE IF NOT EXISTS ai_speech_assistant_knowledge(
9+
`id` INT PRIMARY KEY AUTO_INCREMENT,
10+
`assistant_id` INT NOT NULL,
11+
`json` TEXT NOT NULL,
12+
`prompt` TEXT NOT NULL,
13+
`version` VARCHAR(128) NOT NULL,
14+
`is_active` TINYINT(1) Default 1 NOT NULL,
15+
`created_date` DATETIME(3) NOT NULL,
16+
`created_by` VARCHAR(255) NOT NULL
17+
)CHARSET=utf8mb4;
18+
19+
CREATE TABLE IF NOT EXISTS ai_speech_assistant_greeting(
20+
`id` int PRIMARY KEY AUTO_INCREMENT,
21+
`assistant_id` int NOT NULL,
22+
`text` text NOT NULL,
23+
`version` varchar(128) NOT NULL,
24+
`is_active` tinyint(1) DEFAULT 1 NOT NULL,
25+
`created_date` datetime(3) NOT NULL,
26+
`created_by` varchar(255) NOT NULL
27+
) CHARSET=utf8mb4;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
ALTER TABLE ai_speech_assistant
2+
CHANGE COLUMN did_number answering_number VARCHAR(48) NULL,
3+
CHANGE COLUMN url model_url VARCHAR(255) NULL,
4+
CHANGE COLUMN voice model_voice VARCHAR(36) NULL,
5+
CHANGE COLUMN provider model_provider VARCHAR(255) NULL,
6+
ADD COLUMN answering_number_id INT NOT NULL,
7+
ADD COLUMN created_by VARCHAR(255) NULL;
8+
9+
ALTER TABLE ai_speech_assistant DROP COLUMN greetings, DROP COLUMN custom_record_analyze_prompt;
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using System.ComponentModel.DataAnnotations;
2-
using SmartTalk.Messages.Enums.AiSpeechAssistant;
32
using System.ComponentModel.DataAnnotations.Schema;
3+
using SmartTalk.Messages.Enums.AiSpeechAssistant;
44

55
namespace SmartTalk.Core.Domain.AISpeechAssistant;
66

@@ -15,27 +15,27 @@ public class AiSpeechAssistant : IEntity, IHasCreatedFields
1515
[Column("name"), StringLength(255)]
1616
public string Name { get; set; }
1717

18-
[Column("did_number"), StringLength(32)]
19-
public string DidNumber { get; set; }
18+
[Column("answering_number_id")]
19+
public int AnsweringNumberId { get; set; }
20+
21+
[Column("answering_number")]
22+
public string AnsweringNumber { get; set; }
2023

21-
[Column("url"), StringLength(512)]
22-
public string Url { get; set; }
24+
[Column("model_url")]
25+
public string ModelUrl { get; set; }
2326

24-
[Column("voice"), StringLength(36)]
25-
public string Voice { get; set; }
27+
[Column("model_provider")]
28+
public AiSpeechAssistantProvider ModelProvider { get; set; }
2629

27-
[Column("provider")]
28-
public AiSpeechAssistantProvider Provider { get; set; }
30+
[Column("model_voice")]
31+
public string ModelVoice { get; set; }
2932

3033
[Column("agent_id")]
3134
public int AgentId { get; set; }
3235

33-
[Column("greetings"), StringLength(1024)]
34-
public string Greetings { get; set; }
35-
36-
[Column("custom_record_analyze_prompt")]
37-
public string CustomRecordAnalyzePrompt { get; set; }
38-
3936
[Column("created_date")]
4037
public DateTimeOffset CreatedDate { get; set; }
38+
39+
[Column("created_by")]
40+
public string CreatedBy { get; set; }
4141
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System.ComponentModel.DataAnnotations;
2+
using System.ComponentModel.DataAnnotations.Schema;
3+
4+
namespace SmartTalk.Core.Domain.AIKnowledgeBase;
5+
6+
[Table("ai_speech_assistant_greeting")]
7+
public class AiSpeechAssistantGreeting : IEntity, IHasCreatedFields
8+
{
9+
[Key]
10+
[Column("id")]
11+
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
12+
public int Id { get; set; }
13+
14+
[Column("assistant_id")]
15+
public int AssistantId { get; set; }
16+
17+
[Column("text")]
18+
public string Text { get; set; }
19+
20+
[Column("version")]
21+
public string Version { get; set; }
22+
23+
[Column("is_active", TypeName = "tinyint(1)")]
24+
public bool IsActive { get; set; }
25+
26+
[Column("created_date")]
27+
public DateTimeOffset CreatedDate { get; set; }
28+
29+
[Column("created_by")]
30+
public string CreatedBy { get; set; }
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using System.ComponentModel.DataAnnotations;
2+
using System.ComponentModel.DataAnnotations.Schema;
3+
4+
namespace SmartTalk.Core.Domain.AIKnowledgeBase;
5+
6+
[Table("ai_speech_assistant_knowledge")]
7+
public class AiSpeechAssistantKnowledge : IEntity, IHasCreatedFields
8+
{
9+
[Key]
10+
[Column("id")]
11+
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
12+
public int Id { get; set; }
13+
14+
[Column("assistant_id")]
15+
public int AssistantId { get; set; }
16+
17+
[Column("json")]
18+
public string Json { get; set; }
19+
20+
[Column("prompt")]
21+
public string Prompt { get; set; }
22+
23+
[Column("version")]
24+
public string Version { get; set; }
25+
26+
[Column("is_active", TypeName = "tinyint(1)")]
27+
public bool IsActive { get; set; }
28+
29+
[Column("created_date")]
30+
public DateTimeOffset CreatedDate { get; set; }
31+
32+
[Column("created_by")]
33+
public string CreatedBy { get; set; }
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using System.ComponentModel.DataAnnotations;
2+
using System.ComponentModel.DataAnnotations.Schema;
3+
4+
namespace SmartTalk.Core.Domain.AIKnowledgeBase;
5+
6+
[Table("number_pool")]
7+
public class NumberPool : IEntity, IHasCreatedFields
8+
{
9+
[Key]
10+
[Column("id")]
11+
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
12+
public int Id { get; set; }
13+
14+
[Column("number")]
15+
public string Number { get; set; }
16+
17+
[Column("is_used", TypeName = "tinyint(1)")]
18+
public bool IsUsed { get; set; }
19+
20+
[Column("created_date")]
21+
public DateTimeOffset CreatedDate { get; set; }
22+
}

src/SmartTalk.Core/Services/AiSpeechAssistant/AiSpeechAssistantDataProvider.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ from userProfile in userProfileGroup.DefaultIfEmpty()
4343
assistant, promptTemplate, userProfile
4444
};
4545

46-
assistantInfo = assistantInfo.Where(x => assistantId.HasValue ? x.assistant.Id == assistantId.Value : x.assistant.DidNumber == didNumber);
46+
assistantInfo = assistantInfo.Where(x => assistantId.HasValue ? x.assistant.Id == assistantId.Value : x.assistant.AnsweringNumber == didNumber);
4747

4848
var result = await assistantInfo.FirstOrDefaultAsync(cancellationToken: cancellationToken).ConfigureAwait(false);
4949

@@ -52,7 +52,7 @@ from userProfile in userProfileGroup.DefaultIfEmpty()
5252

5353
public async Task<Domain.AISpeechAssistant.AiSpeechAssistant> GetAiSpeechAssistantByNumbersAsync(string didNumber, CancellationToken cancellationToken)
5454
{
55-
return await _repository.Query<Domain.AISpeechAssistant.AiSpeechAssistant>().Where(x => x.DidNumber == didNumber)
55+
return await _repository.Query<Domain.AISpeechAssistant.AiSpeechAssistant>().Where(x => x.AnsweringNumber == didNumber)
5656
.FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
5757
}
5858

src/SmartTalk.Core/Services/AiSpeechAssistant/AiSpeechAssistantService.cs

+8-9
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
using SmartTalk.Core.Constants;
1414
using Microsoft.AspNetCore.Http;
1515
using OpenAI.Chat;
16-
using SmartTalk.Core.Services.Agents;
1716
using SmartTalk.Core.Services.Http;
1817
using SmartTalk.Core.Services.Http.Clients;
1918
using SmartTalk.Messages.Constants;
@@ -29,8 +28,6 @@
2928
using SmartTalk.Messages.Enums.AiSpeechAssistant;
3029
using SmartTalk.Messages.Events.AiSpeechAssistant;
3130
using SmartTalk.Messages.Commands.AiSpeechAssistant;
32-
using SmartTalk.Messages.Commands.PhoneOrder;
33-
using SmartTalk.Messages.Dto.Agent;
3431
using SmartTalk.Messages.Enums.Agent;
3532
using SmartTalk.Messages.Enums.PhoneOrder;
3633
using JsonSerializer = System.Text.Json.JsonSerializer;
@@ -157,6 +154,8 @@ public async Task ReceivePhoneRecordingStatusCallbackAsync(ReceivePhoneRecording
157154

158155
var (record, agent, aiSpeechAssistant) = await _phoneOrderDataProvider.GetRecordWithAgentAndAssistantAsync(command.CallSid, cancellationToken).ConfigureAwait(false);
159156

157+
var knowledge = await _phoneOrderDataProvider.GetKnowledgePromptByAssistantIdAsync(aiSpeechAssistant.Id, cancellationToken).ConfigureAwait(false);
158+
160159
Log.Information("Get phone order record: {@record}", record);
161160

162161
record.Url = command.RecordingUrl;
@@ -167,9 +166,9 @@ public async Task ReceivePhoneRecordingStatusCallbackAsync(ReceivePhoneRecording
167166
var audioData = BinaryData.FromBytes(audioFileRawBytes);
168167
List<ChatMessage> messages =
169168
[
170-
new SystemChatMessage(string.IsNullOrEmpty(aiSpeechAssistant?.CustomRecordAnalyzePrompt)
169+
new SystemChatMessage(string.IsNullOrEmpty(knowledge?.Prompt)
171170
? "你是一名電話錄音的分析員,通過聽取錄音內容和語氣情緒作出精確分析,冩出一份分析報告。\n\n分析報告的格式:交談主題:xxx\n\n 內容摘要:xxx \n\n 客人情感與情緒: xxx \n\n 待辦事件: \n1.xxx\n2.xxx \n\n 客人下單內容(如果沒有則忽略):1. 牛肉(1箱)\n2.雞腿肉(1箱)"
172-
: aiSpeechAssistant.CustomRecordAnalyzePrompt),
171+
: knowledge.Prompt),
173172
new UserChatMessage(ChatMessageContentPart.CreateInputAudioPart(audioData, ChatInputAudioFormat.Wav)),
174173
new UserChatMessage("幫我根據錄音生成分析報告:")
175174
];
@@ -237,7 +236,7 @@ private async Task<WebSocket> ConnectOpenAiRealTimeSocketAsync(Domain.AISpeechAs
237236
openAiWebSocket.Options.SetRequestHeader("Authorization", GetAuthorizationHeader(assistant));
238237
openAiWebSocket.Options.SetRequestHeader("OpenAI-Beta", "realtime=v1");
239238

240-
var url = string.IsNullOrEmpty(assistant.Url) ? AiSpeechAssistantStore.DefaultUrl : assistant.Url;
239+
var url = string.IsNullOrEmpty(assistant.ModelUrl) ? AiSpeechAssistantStore.DefaultUrl : assistant.ModelUrl;
241240

242241
await openAiWebSocket.ConnectAsync(new Uri(url), cancellationToken).ConfigureAwait(false);
243242

@@ -248,11 +247,11 @@ private async Task<WebSocket> ConnectOpenAiRealTimeSocketAsync(Domain.AISpeechAs
248247

249248
private string GetAuthorizationHeader(Domain.AISpeechAssistant.AiSpeechAssistant assistant)
250249
{
251-
return assistant.Provider switch
250+
return assistant.ModelProvider switch
252251
{
253252
AiSpeechAssistantProvider.OpenAi => $"Bearer {_openAiSettings.ApiKey}",
254253
AiSpeechAssistantProvider.ZhiPuAi => $"Bearer {_zhiPuAiSettings.ApiKey}",
255-
_ => throw new NotSupportedException(nameof(assistant.Provider))
254+
_ => throw new NotSupportedException(nameof(assistant.ModelProvider))
256255
};
257256
}
258257

@@ -739,7 +738,7 @@ private async Task SendSessionUpdateAsync(WebSocket openAiWebSocket, Domain.AISp
739738
turn_detection = new { type = "server_vad" },
740739
input_audio_format = "g711_ulaw",
741740
output_audio_format = "g711_ulaw",
742-
voice = string.IsNullOrEmpty(assistant.Voice) ? "alloy" : assistant.Voice,
741+
voice = string.IsNullOrEmpty(assistant.ModelVoice) ? "alloy" : assistant.ModelVoice,
743742
instructions = prompt,
744743
modalities = new[] { "text", "audio" },
745744
temperature = 0.8,

src/SmartTalk.Core/Services/PhoneOrder/PhoneOrderDataProvider.Record.cs

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
using Microsoft.EntityFrameworkCore;
22
using SmartTalk.Core.Domain.Account;
3+
using SmartTalk.Core.Domain.AIKnowledgeBase;
34
using SmartTalk.Core.Domain.PhoneOrder;
45
using SmartTalk.Core.Domain.Restaurants;
56
using SmartTalk.Core.Domain.System;
6-
using SmartTalk.Messages.Dto.Agent;
77
using SmartTalk.Messages.Dto.PhoneOrder;
88
using SmartTalk.Messages.Dto.Restaurant;
99
using SmartTalk.Messages.Enums.PhoneOrder;
@@ -35,6 +35,8 @@ Task<List<GetPhoneOrderRecordsWithUserCountDto>> GetPhoneOrderRecordsWithUserCou
3535
Task<PhoneOrderRecord> GetPhoneOrderRecordBySessionIdAsync(string sessionId, CancellationToken cancellationToken);
3636

3737
Task<(PhoneOrderRecord, Agent, Domain.AISpeechAssistant.AiSpeechAssistant)> GetRecordWithAgentAndAssistantAsync(string sessionId, CancellationToken cancellationToken);
38+
39+
Task<AiSpeechAssistantKnowledge> GetKnowledgePromptByAssistantIdAsync(int assistantId, CancellationToken cancellationToken);
3840
}
3941

4042
public partial class PhoneOrderDataProvider
@@ -194,4 +196,9 @@ from assistant in assistantGroup.DefaultIfEmpty()
194196

195197
return (result?.record, result?.agent, result?.assistant);
196198
}
199+
200+
public async Task<AiSpeechAssistantKnowledge> GetKnowledgePromptByAssistantIdAsync(int assistantId, CancellationToken cancellationToken)
201+
{
202+
return await _repository.Query<AiSpeechAssistantKnowledge>().Where(x=>x.AssistantId == assistantId).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
203+
}
197204
}

0 commit comments

Comments
 (0)