Skip to content

Commit d07f011

Browse files
committed
feat: 모든 DTO를 ChatProcessContext를 통해 처리
set을 통한 접근제어
1 parent 0948bc7 commit d07f011

File tree

14 files changed

+170
-339
lines changed

14 files changed

+170
-339
lines changed

ProjectVG.Application/Models/Chat/ChatMessageSegment.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ public static ChatMessageSegment CreateTextOnly(string text, int order = 0)
2222
Order = order
2323
};
2424
}
25+
26+
public void SetAudioData(byte[]? audioData, string? audioContentType, float? audioLength)
27+
{
28+
AudioData = audioData;
29+
AudioContentType = audioContentType;
30+
AudioLength = audioLength;
31+
}
2532

2633

2734
}

ProjectVG.Application/Models/Chat/ChatPreprocessContext.cs

Lines changed: 0 additions & 86 deletions
This file was deleted.

ProjectVG.Application/Models/Chat/ChatPreprocessResult.cs

Lines changed: 0 additions & 27 deletions
This file was deleted.
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
using ProjectVG.Application.Models.Character;
2+
using ProjectVG.Domain.Entities.ConversationHistorys;
3+
4+
namespace ProjectVG.Application.Models.Chat
5+
{
6+
public class ChatProcessContext
7+
{
8+
public string SessionId { get; private set; } = string.Empty;
9+
public Guid UserId { get; private set; }
10+
public Guid CharacterId { get; private set; }
11+
public string UserMessage { get; private set; } = string.Empty;
12+
public string MemoryStore { get; private set; } = string.Empty;
13+
14+
public CharacterDto? Character { get; private set; }
15+
public IEnumerable<string>? MemoryContext { get; private set; }
16+
public IEnumerable<ConversationHistory>? ConversationHistory { get; private set; }
17+
18+
public string Response { get; private set; } = string.Empty;
19+
public double Cost { get; private set; }
20+
public List<ChatMessageSegment> Segments { get; private set; } = new List<ChatMessageSegment>();
21+
22+
public string FullText => string.Join(" ", Segments.Where(s => s.HasText).Select(s => s.Text));
23+
public bool HasAudio => Segments.Any(s => s.HasAudio);
24+
public bool HasText => Segments.Any(s => s.HasText);
25+
26+
27+
public ChatProcessContext(ProcessChatCommand command)
28+
{
29+
SessionId = command.SessionId;
30+
UserId = command.UserId;
31+
CharacterId = command.CharacterId;
32+
UserMessage = command.Message;
33+
MemoryStore = command.UserId.ToString();
34+
}
35+
36+
public ChatProcessContext(
37+
ProcessChatCommand command,
38+
CharacterDto character,
39+
IEnumerable<ConversationHistory> conversationHistory,
40+
IEnumerable<string> memoryContext)
41+
{
42+
SessionId = command.SessionId;
43+
UserId = command.UserId;
44+
CharacterId = command.CharacterId;
45+
UserMessage = command.Message;
46+
MemoryStore = command.UserId.ToString();
47+
48+
Character = character;
49+
ConversationHistory = conversationHistory;
50+
MemoryContext = memoryContext;
51+
}
52+
53+
public void SetResponse(string response, List<ChatMessageSegment> segments, double cost)
54+
{
55+
Response = response;
56+
Segments = segments;
57+
Cost = cost;
58+
}
59+
60+
public void AddCost(double additionalCost)
61+
{
62+
Cost += additionalCost;
63+
}
64+
65+
public IEnumerable<string> ParseConversationHistory(int count = 5)
66+
{
67+
if (ConversationHistory == null) return Enumerable.Empty<string>();
68+
69+
return ConversationHistory
70+
.Take(count)
71+
.Select(h => $"{h.Role}: {h.Content}");
72+
}
73+
}
74+
}

ProjectVG.Application/Models/Chat/ChatProcessResult.cs

Lines changed: 0 additions & 16 deletions
This file was deleted.

ProjectVG.Application/Models/Chat/ProcessChatCommand.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ public string RequestId
1919
public string? Action { get; set; }
2020
public string? Instruction { get; set; }
2121

22+
2223
public CharacterDto? Character { get; private set; }
2324

2425
internal void SetCharacter(CharacterDto character)

ProjectVG.Application/Services/Chat/ChatService.cs

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -79,39 +79,33 @@ public async Task<ChatRequestResponse> EnqueueChatRequestAsync(ProcessChatComman
7979
/// <summary>
8080
/// 채팅 요청 준비
8181
/// </summary>
82-
private async Task<ChatPreprocessContext> PrepareChatRequestAsync(ProcessChatCommand command)
82+
private async Task<ChatProcessContext> PrepareChatRequestAsync(ProcessChatCommand command)
8383
{
8484
var characterDto = await _characterService.GetCharacterByIdAsync(command.CharacterId);
85-
command.SetCharacter(characterDto!);
86-
8785
var conversationHistory = await _conversationService.GetConversationHistoryAsync(command.UserId, command.CharacterId, 10);
8886

8987
var inputAnalysis = await _inputProcessor.ProcessAsync(command.Message, conversationHistory);
9088
await _actionProcessor.ProcessAsync(command, inputAnalysis);
9189

9290
var memoryContext = await _memoryPreprocessor.CollectMemoryContextAsync(command.UserId.ToString(), command.Message, inputAnalysis);
9391

94-
return new ChatPreprocessContext(
95-
command,
96-
memoryContext,
97-
conversationHistory
98-
);
92+
return new ChatProcessContext(command, characterDto!, conversationHistory, memoryContext);
9993
}
10094

10195
/// <summary>
10296
/// 채팅 요청 처리
10397
/// </summary>
104-
private async Task ProcessChatRequestInternalAsync(ChatPreprocessContext context)
98+
private async Task ProcessChatRequestInternalAsync(ChatProcessContext context)
10599
{
106100
try {
107101
// 작업 처리 단계: LLM -> TTS -> 결과 전송 + 저장
108-
var llmResult = await _llmProcessor.ProcessAsync(context);
109-
await _ttsProcessor.ProcessAsync(context, llmResult);
102+
await _llmProcessor.ProcessAsync(context);
103+
await _ttsProcessor.ProcessAsync(context);
110104

111105
using var scope = _scopeFactory.CreateScope();
112106
var resultProcessor = scope.ServiceProvider.GetRequiredService<ChatResultProcessor>();
113-
await resultProcessor.SendResultsAsync(context, llmResult);
114-
await resultProcessor.PersistResultsAsync(context, llmResult);
107+
await resultProcessor.SendResultsAsync(context);
108+
await resultProcessor.PersistResultsAsync(context);
115109
}
116110
catch (Exception ex) {
117111
await _failureHandler.HandleFailureAsync(context, ex);

ProjectVG.Application/Services/Chat/CostTracking/CostTrackingDecorator.cs

Lines changed: 6 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,14 @@ private decimal ExtractCost(object? result)
4040
return 0;
4141
}
4242

43-
public async Task<ChatProcessResult> ProcessAsync(ChatPreprocessContext context)
43+
public async Task ProcessAsync(ChatProcessContext context)
4444
{
4545
_metricsService.StartProcessMetrics(_processName);
4646

4747
try
4848
{
4949
// 리플렉션으로 ProcessAsync 메서드 호출
50-
var method = typeof(T).GetMethod("ProcessAsync", new[] { typeof(ChatPreprocessContext) });
50+
var method = typeof(T).GetMethod("ProcessAsync", new[] { typeof(ChatProcessContext) });
5151

5252
if (method == null)
5353
throw new InvalidOperationException($"ProcessAsync 메서드를 찾을 수 없습니다: {typeof(T).Name}");
@@ -56,51 +56,15 @@ public async Task<ChatProcessResult> ProcessAsync(ChatPreprocessContext context)
5656
if (invokeResult == null)
5757
throw new InvalidOperationException($"ProcessAsync 메서드 호출 결과가 null입니다: {typeof(T).Name}");
5858

59-
if (invokeResult is not Task<ChatProcessResult> taskResult)
60-
throw new InvalidOperationException($"ProcessAsync 메서드 반환 타입이 올바르지 않습니다: {typeof(T).Name}");
61-
62-
var result = await taskResult!;
63-
64-
// Cost 값만 직접 추출
65-
var cost = ExtractCost(result);
66-
Console.WriteLine($"[COST_TRACKING] {_processName} - 추출된 비용: {cost:F0} Cost");
67-
Console.WriteLine($"[COST_TRACKING] {_processName} - 원본 결과 타입: {result?.GetType().Name}, Cost 속성 값: {result?.GetType().GetProperty("Cost")?.GetValue(result)}");
68-
_metricsService.EndProcessMetrics(_processName, cost);
69-
return result;
70-
}
71-
catch (Exception ex)
72-
{
73-
_metricsService.EndProcessMetrics(_processName, 0, ex.Message);
74-
throw;
75-
}
76-
}
77-
78-
public async Task ProcessAsync(ChatPreprocessContext context, ChatProcessResult result)
79-
{
80-
_metricsService.StartProcessMetrics(_processName);
81-
82-
try
83-
{
84-
// 리플렉션으로 ProcessAsync 메서드 호출 (void 반환)
85-
var method = typeof(T).GetMethod("ProcessAsync",
86-
new[] { typeof(ChatPreprocessContext), typeof(ChatProcessResult) });
87-
88-
if (method == null)
89-
throw new InvalidOperationException($"ProcessAsync 메서드를 찾을 수 없습니다: {typeof(T).Name}");
90-
91-
var invokeResult = method.Invoke(_service, new object[] { context, result });
92-
if (invokeResult == null)
93-
throw new InvalidOperationException($"ProcessAsync 메서드 호출 결과가 null입니다: {typeof(T).Name}");
94-
9559
if (invokeResult is not Task taskResult)
9660
throw new InvalidOperationException($"ProcessAsync 메서드 반환 타입이 올바르지 않습니다: {typeof(T).Name}");
9761

9862
await taskResult;
9963

10064
// Cost 값만 직접 추출
101-
var cost = ExtractCost(result);
65+
var cost = ExtractCost(context);
10266
Console.WriteLine($"[COST_TRACKING] {_processName} - 추출된 비용: {cost:F0} Cost");
103-
Console.WriteLine($"[COST_TRACKING] {_processName} - 원본 결과 타입: {result?.GetType().Name}, Cost 속성 값: {result?.GetType().GetProperty("Cost")?.GetValue(result)}");
67+
Console.WriteLine($"[COST_TRACKING] {_processName} - 컨텍스트 타입: {context?.GetType().Name}, Cost 속성 값: {context?.GetType().GetProperty("Cost")?.GetValue(context)}");
10468
_metricsService.EndProcessMetrics(_processName, cost);
10569
}
10670
catch (Exception ex)
@@ -110,6 +74,8 @@ public async Task ProcessAsync(ChatPreprocessContext context, ChatProcessResult
11074
}
11175
}
11276

77+
78+
11379
public async Task<UserInputAnalysis> ProcessAsync(string userInput, IEnumerable<ConversationHistory> conversationHistory)
11480
{
11581
_metricsService.StartProcessMetrics(_processName);

ProjectVG.Application/Services/Chat/CostTracking/ICostTrackingDecorator.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ namespace ProjectVG.Application.Services.Chat.CostTracking
66
public interface ICostTrackingDecorator<T> where T : class
77
{
88
T Service { get; }
9-
Task<ChatProcessResult> ProcessAsync(ChatPreprocessContext context);
10-
Task ProcessAsync(ChatPreprocessContext context, ChatProcessResult result);
9+
Task ProcessAsync(ChatProcessContext context);
1110
Task<UserInputAnalysis> ProcessAsync(string userInput, IEnumerable<ConversationHistory> conversationHistory);
1211
}
1312
}

0 commit comments

Comments
 (0)