Skip to content

Commit 0948bc7

Browse files
committed
fix: LLM 결과 처리 단계 축소
1 parent a050c89 commit 0948bc7

File tree

5 files changed

+52
-137
lines changed

5 files changed

+52
-137
lines changed

ProjectVG.Application/Models/Chat/ChatMessageSegment.cs

Lines changed: 1 addition & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -13,51 +13,6 @@ public class ChatMessageSegment
1313
public bool HasAudio => AudioData != null && AudioData.Length > 0;
1414
public bool IsEmpty => !HasText && !HasAudio;
1515

16-
public override string ToString()
17-
{
18-
var parts = new List<string>();
19-
20-
parts.Add($"Order: {Order}");
21-
22-
if (HasText)
23-
{
24-
parts.Add($"Text: \"{Text}\"");
25-
}
26-
27-
if (HasAudio)
28-
{
29-
parts.Add($"Audio: {AudioData!.Length} bytes, {AudioContentType}, {AudioLength:F2}s");
30-
}
31-
32-
if (!string.IsNullOrEmpty(Emotion))
33-
{
34-
parts.Add($"Emotion: {Emotion}");
35-
}
36-
37-
return $"Segment({string.Join(", ", parts)})";
38-
}
39-
40-
public string ToShortString()
41-
{
42-
var parts = new List<string>();
43-
44-
if (HasText)
45-
{
46-
parts.Add($"\"{Text}\"");
47-
}
48-
49-
if (HasAudio)
50-
{
51-
parts.Add($"[Audio: {AudioLength:F1}s]");
52-
}
53-
54-
return string.Join(" ", parts);
55-
}
56-
57-
public string ToDebugString()
58-
{
59-
return $"Segment[Order={Order}, Text={HasText}, Audio={HasAudio}, Emotion={Emotion ?? "none"}, AudioSize={AudioData?.Length ?? 0} bytes, AudioLength={AudioLength:F2}s]";
60-
}
6116

6217
public static ChatMessageSegment CreateTextOnly(string text, int order = 0)
6318
{
@@ -68,28 +23,6 @@ public static ChatMessageSegment CreateTextOnly(string text, int order = 0)
6823
};
6924
}
7025

71-
public static ChatMessageSegment CreateAudioOnly(byte[] audioData, string contentType, float? audioLength, int order = 0)
72-
{
73-
return new ChatMessageSegment
74-
{
75-
AudioData = audioData,
76-
AudioContentType = contentType,
77-
AudioLength = audioLength,
78-
Order = order
79-
};
80-
}
81-
82-
public static ChatMessageSegment CreateIntegrated(string text, byte[] audioData, string contentType, float? audioLength, string? emotion = null, int order = 0)
83-
{
84-
return new ChatMessageSegment
85-
{
86-
Text = text,
87-
AudioData = audioData,
88-
AudioContentType = contentType,
89-
AudioLength = audioLength,
90-
Emotion = emotion,
91-
Order = order
92-
};
93-
}
26+
9427
}
9528
}

ProjectVG.Application/Models/Chat/ChatOutputFormatResult.cs

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

ProjectVG.Application/Models/Chat/ChatProcessResult.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ namespace ProjectVG.Application.Models.Chat
33
public class ChatProcessResult
44
{
55
public string Response { get; set; } = string.Empty;
6-
public int TokensUsed { get; set; }
76
public double Cost { get; set; }
87

98
public List<ChatMessageSegment> Segments { get; set; } = new List<ChatMessageSegment>();

ProjectVG.Application/Services/Chat/Factories/ChatLLMFormat.cs

Lines changed: 45 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
namespace ProjectVG.Application.Services.Chat.Factories
77
{
8-
public class ChatLLMFormat : ILLMFormat<ChatPreprocessContext, ChatOutputFormatResult>
8+
public class ChatLLMFormat : ILLMFormat<ChatPreprocessContext, List<ChatMessageSegment>>
99
{
1010
public ChatLLMFormat()
1111
{
@@ -29,7 +29,6 @@ public string GetInstructions(ChatPreprocessContext input)
2929
{
3030
var sb = new StringBuilder();
3131

32-
// 메모리 컨텍스트 추가
3332
if (input.MemoryContext?.Any() == true)
3433
{
3534
sb.AppendLine("관련 기억:");
@@ -40,7 +39,6 @@ public string GetInstructions(ChatPreprocessContext input)
4039
sb.AppendLine();
4140
}
4241

43-
// 대화 기록 추가
4442
var conversationHistory = input.ParseConversationHistory(5);
4543
if (conversationHistory.Any())
4644
{
@@ -52,7 +50,6 @@ public string GetInstructions(ChatPreprocessContext input)
5250
sb.AppendLine();
5351
}
5452

55-
// 출력 포맷 지침 추가
5653
sb.AppendLine(GetFormatInstructions());
5754

5855
return sb.ToString();
@@ -62,9 +59,9 @@ public string GetInstructions(ChatPreprocessContext input)
6259
public float Temperature => 0.7f;
6360
public int MaxTokens => 1000;
6461

65-
public ChatOutputFormatResult Parse(string llmResponse, ChatPreprocessContext input)
62+
public List<ChatMessageSegment> Parse(string llmResponse, ChatPreprocessContext input)
6663
{
67-
return ParseChatResponse(llmResponse, input.VoiceName);
64+
return ParseChatResponseToSegments(llmResponse, input.VoiceName);
6865
}
6966

7067
public double CalculateCost(int promptTokens, int completionTokens)
@@ -85,54 +82,63 @@ [neutral] 내가 그런다고 좋아할 것 같아? [shy] 하지만 츄 해준
8582
";
8683
}
8784

88-
private ChatOutputFormatResult ParseChatResponse(string llmText, string? voiceName = null)
85+
private List<ChatMessageSegment> ParseChatResponseToSegments(string llmText, string? voiceName = null)
8986
{
9087
if (string.IsNullOrWhiteSpace(llmText))
91-
return new ChatOutputFormatResult();
88+
return new List<ChatMessageSegment>();
9289

9390
string response = llmText.Trim();
94-
var emotions = new List<string>();
95-
var texts = new List<string>();
91+
var segments = new List<ChatMessageSegment>();
92+
var seenTexts = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
9693

97-
// [감정] 답변 패턴 추출
9894
var matches = Regex.Matches(response, @"\[(.*?)\]\s*([^\[]+)");
99-
100-
// 보이스별 감정 매핑
101-
Dictionary<string, string>? emotionMap = null;
102-
if (!string.IsNullOrWhiteSpace(voiceName))
103-
{
104-
var profile = VoiceCatalog.GetProfile(voiceName);
105-
if (profile != null && profile.EmotionMap != null)
106-
emotionMap = profile.EmotionMap;
107-
}
95+
var emotionMap = GetEmotionMap(voiceName);
10896

10997
if (matches.Count > 0)
11098
{
111-
foreach (Match match in matches)
112-
{
113-
if (match.Groups.Count >= 3)
114-
{
115-
var originalEmotion = match.Groups[1].Value.Trim();
116-
var mappedEmotion = emotionMap != null && emotionMap.ContainsKey(originalEmotion)
117-
? emotionMap[originalEmotion]
118-
: originalEmotion;
119-
emotions.Add(mappedEmotion);
120-
texts.Add(match.Groups[2].Value.Trim());
121-
}
122-
}
99+
ProcessMatches(matches, emotionMap, segments, seenTexts);
123100
}
124101
else
125102
{
126-
emotions.Add("neutral");
127-
texts.Add(response);
103+
var segment = ChatMessageSegment.CreateTextOnly(response, 0);
104+
segment.Emotion = "neutral";
105+
segments.Add(segment);
128106
}
129107

130-
return new ChatOutputFormatResult
108+
return segments;
109+
}
110+
111+
private Dictionary<string, string>? GetEmotionMap(string? voiceName)
112+
{
113+
if (string.IsNullOrWhiteSpace(voiceName))
114+
return null;
115+
116+
var profile = VoiceCatalog.GetProfile(voiceName);
117+
return profile?.EmotionMap;
118+
}
119+
120+
private void ProcessMatches(MatchCollection matches, Dictionary<string, string>? emotionMap, List<ChatMessageSegment> segments, HashSet<string> seenTexts)
121+
{
122+
for (int i = 0; i < matches.Count; i++)
131123
{
132-
Response = response,
133-
Emotion = emotions,
134-
Text = texts
135-
};
124+
var match = matches[i];
125+
if (match.Groups.Count >= 3)
126+
{
127+
var originalEmotion = match.Groups[1].Value.Trim();
128+
var mappedEmotion = emotionMap != null && emotionMap.ContainsKey(originalEmotion)
129+
? emotionMap[originalEmotion]
130+
: originalEmotion;
131+
var text = match.Groups[2].Value.Trim();
132+
133+
if (!seenTexts.Contains(text))
134+
{
135+
seenTexts.Add(text);
136+
var segment = ChatMessageSegment.CreateTextOnly(text, segments.Count);
137+
segment.Emotion = mappedEmotion;
138+
segments.Add(segment);
139+
}
140+
}
141+
}
136142
}
137143
}
138144
}

ProjectVG.Application/Services/Chat/Processors/ChatLLMProcessor.cs

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -32,33 +32,19 @@ public async Task<ChatProcessResult> ProcessAsync(ChatPreprocessContext context)
3232
temperature: format.Temperature
3333
);
3434

35-
// 결과 파싱
36-
var parsed = format.Parse(llmResponse.Response, context);
35+
var segments = format.Parse(llmResponse.Response, context);
36+
3737
var cost = format.CalculateCost(llmResponse.InputTokens, llmResponse.OutputTokens);
38-
var segments = CreateSegments(parsed);
3938

40-
Console.WriteLine($"[LLM_DEBUG] ID: {llmResponse.Id}, 입력 토큰: {llmResponse.InputTokens}, 출력 토큰: {llmResponse.OutputTokens}, 총 토큰: {llmResponse.TokensUsed}, 계산된 비용: {cost:F0} Cost");
41-
_logger.LogDebug("LLM 처리 완료: 세션 {SessionId}, ID {Id}, 입력 토큰 {InputTokens}, 출력 토큰 {OutputTokens}, 총 토큰 {TotalTokens}, 비용 {Cost}",
42-
context.SessionId, llmResponse.Id, llmResponse.InputTokens, llmResponse.OutputTokens, llmResponse.TokensUsed, cost);
39+
Console.WriteLine($"[LLM_DEBUG] ID: {llmResponse.Id}, 입력 토큰: {llmResponse.InputTokens}, 출력 토큰: {llmResponse.OutputTokens}, 계산된 비용: {cost:F0} Cost");
40+
_logger.LogDebug("LLM 처리 완료: 세션 {SessionId}, ID {Id}, 입력 토큰 {InputTokens}, 출력 토큰 {OutputTokens}, 비용 {Cost}",
41+
context.SessionId, llmResponse.Id, llmResponse.InputTokens, llmResponse.OutputTokens, cost);
4342

4443
return new ChatProcessResult {
45-
Response = parsed.Response,
44+
Response = llmResponse.Response,
4645
Segments = segments,
47-
TokensUsed = llmResponse.TokensUsed,
4846
Cost = cost
4947
};
5048
}
51-
52-
private List<ChatMessageSegment> CreateSegments(ChatOutputFormatResult parsed)
53-
{
54-
var segments = new List<ChatMessageSegment>();
55-
for (int i = 0; i < parsed.Text.Count; i++) {
56-
var emotion = parsed.Emotion.Count > i ? parsed.Emotion[i] : "neutral";
57-
var segment = ChatMessageSegment.CreateTextOnly(parsed.Text[i], i);
58-
segment.Emotion = emotion;
59-
segments.Add(segment);
60-
}
61-
return segments;
62-
}
6349
}
6450
}

0 commit comments

Comments
 (0)