-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathtranslator.py
More file actions
294 lines (249 loc) · 8.63 KB
/
Copy pathtranslator.py
File metadata and controls
294 lines (249 loc) · 8.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
import os
from typing import List, Tuple
from dotenv import load_dotenv
load_dotenv()
# =========================================================
# Translator (기존 구조 유지 – 실제 API 번역은 사용 안 함)
# =========================================================
class Translator:
def __init__(self):
# 기존 코드 호환용
self.enabled = False
def translate(self, en_text: str) -> str:
# ❗ 의도적으로 아무 것도 하지 않음 (기존 설계 유지)
return en_text.strip()
# =========================================================
# GPT-4o 기반 문장 보정기 (추가된 부분)
# =========================================================
def ko_sentence_from_gpt(kor_tokens: List[str]) -> str:
"""
GPT-4o를 사용해 '단어 나열 → 자연스러운 한국어 문장'으로 보정
❗ 정보 추가 / 상상 절대 금지
"""
if not kor_tokens:
return ""
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
return ""
try:
from openai import OpenAI
client = OpenAI(api_key=api_key)
system_prompt = (
"You are a Korean language corrector that refines Korean Sign Language (KSL) recognition results into sentences.\n"
"The input is a sequence of meaningful words that may have broken grammar.\n"
"You must NEVER add information that is not present in the input."
)
user_prompt = f"""
Input word list:
{kor_tokens}
Rules:
- Preserve the meaning of input words as much as possible
- NEVER imagine or add actions, times, objects, emotions, or any other information which is not in the input
- Only minimally correct particles (postpositions) and word order
- Use casual speech (반말), NOT formal/polite speech (존댓말)
- Output as a single natural declarative sentence
- Provide ONLY the sentence - no explanations, commentary, or quotation marks
- When uncertain, be conservative and keep it short
- Result MUST only be in KOREAN
Forbidden Additions:
- No intensifiers (very, really, extremely) unless in input
- No connecting words (however, therefore, but) between single sentences
- No pronouns (I, you, he/she) unless explicitly signed
- No descriptive adjectives beyond what's in the input
- No temporal context (today, yesterday, later) unless present
Output Format:
- Maximum one sentence per input
- Prefer shorter constructions when ambiguous
- If input is fragmented/unclear, output the most literal interpretation
- Remove redundant particles rather than adding missing ones
CRITICAL - Priority 1:
1. NEVER infer implied subjects (I/you/we) from context
2. NEVER add causality (because, so, therefore)
3. NEVER specify unmentioned locations/times
4. NEVER elaborate on emotions/states
5. When multiple interpretations exist → choose the most literal/conservative
Priority 2 - Minimal Correction:
1. Only add particles that are 100% necessary for basic grammar
2. Prefer dropping particles over guessing wrong ones
3. Keep original word order unless grammatically impossible
4. Don't "fix" regional dialects or colloquialisms
Example Inputs and Outputs:
- Input: ["나", "밥", "먹다"]
Output: "나는 밥을 먹는다."
- Input: ["어제", "학교", "가다"]
Output: "어제 학교에 갔다."
- Input: ["나", "보다", "영화"]
Output: "나는 영화를 본다."
- Input: ["친구", "나", "버스", "타다"]
Output: "친구와 나는 버스를 탄다."
- Input: ["서울", "부모님", "보다"]
Output: "서울에서 부모님을 본다."
- Input: ["여동생", "어제", "영화", "보다"]
Output: "여동생은 어제 영화를 봤다."
- Input: ["우리", "지금", "지하철", "타다"]
Output: "우리는 지금 지하철을 탄다."
- Input: ["서울", "어디", "위치", "묻다"]
Output: "서울이 어디에 위치했는지 묻는다."
- Input: ["가족", "저녁", "음식", "먹다"]
Output: "가족은 저녁에 음식을 먹는다."
- Input: ["어제", "시험", "끝", "괜찮다"]
Output: "어제 시험이 끝나서 괜찮다."
- Input: ["지금", "버스", "타다", "도착하다"]
Output: "지금 버스를 타고 도착한다."
- Input: ["가족", "나이", "몇", "묻다"]
Output: "가족의 나이가 몇인지 묻는다."
- Input: ["저녁", "비빔밥", "먹다", "좋다"]
Output: "저녁에 비빔밥을 먹어서 좋다."
- Input: ["우리", "노력", "마침내", "성공"]
Output: "우리는 노력해서 마침내 성공했다."
Output:
"""
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_prompt},
],
temperature=0.15,
)
text = response.choices[0].message.content.strip()
if text and text[-1] not in ".!?":
text += "."
return text
except Exception as e:
print("GPT sentence error:", e)
return ""
# =========================================================
# 기존 규칙 기반 문장 생성 (❗ 수정하지 않음)
# =========================================================
TOKEN_TYPE = {
# 주어 / 인물
"나": "subject",
"너": "subject",
"우리": "subject",
"누구": "subject",
"사람": "subject",
"가족": "subject",
"여동생": "subject",
# 동작 / 상태 (동사·형용사)
"만나다": "verb",
"보다": "verb",
"먹다": "verb",
"타다": "verb",
"도착하다": "verb",
"묻다": "verb",
"걷다": "verb",
"공부하다": "verb",
"받다": "verb",
"걱정하다": "verb",
"태어나다": "verb",
"원하다": "verb",
"좋다": "adjective",
"괜찮다": "adjective",
"반갑다": "adjective",
"미안하다": "adjective",
"감사하다": "adjective",
"아니": "adjective",
"잘": "adverb",
"조심": "adverb",
# 사물 / 대상
"비빔밥": "object",
"영화": "object",
"얼굴": "object",
"이름": "object",
"핸드폰": "object",
"시험": "object",
"음식": "object",
"책임": "object",
"경험": "object",
"노력": "object",
"수고": "object",
"부탁": "object",
"결혼": "object",
"땀": "object",
# 장소
"서울": "place",
"지하철": "place",
"버스": "place",
"위치": "place",
# 시간
"어제": "time",
"지금": "time",
"언제": "time",
"날": "time",
"시간": "time",
"저녁": "time",
"한시간": "time",
"아직": "time",
"다시": "time",
"마침내": "time",
# 수량 / 질문
"몇": "quantity",
"나이": "quantity",
"어디": "question",
# 기타 수식
"특별한": "modifier",
"초대": "event",
"성공": "event",
"끝": "event",
"취미": "topic"
}
def ko_sentence_from_kor_tokens(kor_tokens: List[str]) -> str:
if not kor_tokens:
return ""
time = []
subject = []
obj = []
verb = []
adjective = []
adverb = []
etc = []
for tok in kor_tokens:
t = TOKEN_TYPE.get(tok)
if t == "time":
time.append(tok)
elif t == "subject":
subject.append(tok)
elif t == "object" or t == "place":
obj.append(tok)
elif t == "verb":
verb.append(tok)
elif t == "adjective":
adjective.append(tok)
elif t == "adverb":
adverb.append(tok)
else:
etc.append(tok)
parts = []
parts.extend(time)
parts.extend(subject)
parts.extend(obj)
parts.extend(etc)
parts.extend(verb)
parts.extend(adjective)
parts.extend(adverb)
if not parts:
return ""
sent = " ".join(parts)
return sent + "."
# =========================================================
# 최종 문장 생성 진입점 (기존 구조 유지 + GPT 우선)
# =========================================================
def make_final_korean_sentence(
translator: Translator,
sentence_eng: List[str],
sentence_kor: List[str]
) -> Tuple[str, str]:
# 영어 디버그 문장 (기존 용도 유지)
en_sent = " ".join(sentence_eng).strip()
if en_sent:
en_sent = en_sent[0].upper() + en_sent[1:] + "."
# ✅ 1️⃣ GPT-4o 우선
ko_sent = ko_sentence_from_gpt(sentence_kor)
# ✅ 2️⃣ GPT 실패 → 기존 규칙 기반
if not ko_sent.strip():
ko_sent = ko_sentence_from_kor_tokens(sentence_kor)
# ✅ 3️⃣ 최후 fallback
if not ko_sent.strip():
ko_sent = " ".join(sentence_kor) if sentence_kor else "인식된 단어가 없습니다."
return en_sent, ko_sent