Files
P2EP_Export/UnRLE/0864_DemnCONTC/LLM/contact_llm.py
2026-02-28 02:40:43 +05:00

129 lines
5.3 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import os
import sys
import argparse
import re
from pathlib import Path
import ollama
from tqdm import tqdm
print("=== Persona2 ContactShit LLM Translator ===\n")
# ====================== НАСТРОЙКИ ======================
MODEL = "qwen3:14b-q4_K_M"
DEFAULT_MAX_DIALOGUES = 0 # 0 = все диалоги
DEFAULT_CHUNK_SIZE = 15
TEMPERATURE = 0.25
CONTEXT = 16384
# ======================================================
parser = argparse.ArgumentParser(description="Перевод скриптов Persona 2 через Ollama")
parser.add_argument('-max', type=int, default=DEFAULT_MAX_DIALOGUES,
help='Максимальное количество диалогов для обработки из файла (0 = все)')
parser.add_argument('-chunk', type=int, default=DEFAULT_CHUNK_SIZE,
help='Размер чанка в диалогах (по умолчанию 15)')
args = parser.parse_args()
MAX_DIALOGUES = args.max
CHUNK_SIZE = args.chunk
# --------------------- ПРОМПТ ---------------------
SYSTEM_PROMPT = """Ты — профессиональный локализатор японских RPG (Persona) на русский язык.
Правила (строго соблюдать):
- Строки, начинающиеся с \\ — английский оригинал. Никогда их не трогай и не переводи.
- Все теги [xxxx] оставляй точно как есть, в том же порядке и количестве.
- Сохраняй все отступы, пустые строки и структуру.
- Переводи АНГЛИЙСКИЙ ТЕКСТ, который выше, заменяя японский текст на русский, учитывая контекст японского.
- Стиль: естественный, разговорный, соответствующий персонажу.
- Каждая строка диалога — максимум 47 символов.
- Одно диалоговое окно — не более 3 строк + первая строка с именем/тегами.
Выводи ТОЛЬКО готовый скрипт в исходном формате. Ничего лишнего."""
# ======================================================
def get_dialogue_blocks(lines):
"""Разбивает на диалоги по [0611][0211][0311] без \\ в начале"""
dialogues = []
current = []
for line in lines:
stripped = line.strip()
current.append(line) # сохраняем оригинальную строку
if re.search(r'\[0611\]\[0211\]\[0311\]', stripped) and not stripped.startswith('\\'):
dialogues.append(''.join(current).rstrip('\n'))
current = []
if current:
dialogues.append(''.join(current).rstrip('\n'))
return dialogues
# Поиск файлов
txt_files = [f for f in Path('.').glob('*.txt')
if f.is_file() and "LLM" not in f.name.upper()]
if not txt_files:
print("Не найдено .txt файлов для обработки.")
sys.exit(0)
print(f"Найдено файлов: {len(txt_files)}\n")
for file_path in txt_files:
print(f"▶ Обработка: {file_path.name}")
with open(file_path, 'r', encoding='utf-8') as f:
lines = f.readlines()
if not lines:
continue
header = lines[0].strip()
body_lines = lines[1:]
dialogues = get_dialogue_blocks(body_lines)
total = len(dialogues)
if MAX_DIALOGUES > 0:
dialogues = dialogues[:MAX_DIALOGUES]
print(f" → Обрабатываем только первые {len(dialogues)} из {total} диалогов")
if not dialogues:
print(" Нет диалогов.")
continue
# Разбиваем на чанки
chunks = [dialogues[i:i + CHUNK_SIZE] for i in range(0, len(dialogues), CHUNK_SIZE)]
translated_chunks = []
for i, chunk in enumerate(tqdm(chunks, desc=" Чанки", leave=False)):
chunk_text = '\n'.join(chunk) # без лишних пустых строк между диалогами внутри чанка
try:
response = ollama.chat(
model=MODEL,
messages=[
{'role': 'system', 'content': SYSTEM_PROMPT},
{'role': 'user', 'content': f"Переведи этот фрагмент скрипта:\n\n{chunk_text}"}
],
options={'temperature': TEMPERATURE, 'num_ctx': CONTEXT}
)
translated_chunks.append(response['message']['content'].strip())
except Exception as e:
print(f"\n Ошибка в чанке {i+1}: {e}")
break
# Финальная сборка БЕЗ лишних пустых строк между чанками
final_content = header + "\n" + "\n".join(translated_chunks)
output_path = file_path.with_name(f"{file_path.stem}_LLM{file_path.suffix}")
with open(output_path, 'w', encoding='utf-8') as f:
f.write(final_content)
print(f" ✓ Готово → {output_path.name} ({len(dialogues)} диалогов)\n")
print("=== Все файлы обработаны! ===")