Files
homeclaw/.smallclaw/databases/translate_api.py
T
kimandClaude Sonnet 4.6 508d11615a Add user workspaces, dental DB scripts, server memory + code editor improvements
- cherry: orofacial/TMD PPTX presentations + 음악가 구강건강 가이드
- papa: sinus/infraoccluded PPTX, garden-monitor Arduino, MIDI files
- databases: PCSP scraper, translation scripts, vision benchmark, batch JSONs
- web-ui: code.js/companion.py/styles.css major updates, autostart installer
- src: ollama-client, session, LLMProvider, ollama-adapter patches
- .gitignore: add claude-key, SQLite WAL/SHM, __pycache__, nohup.out

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 23:13:03 +09:00

121 lines
4.2 KiB
Python

#!/usr/bin/env python3
"""Batch translate PCSP article titles to Korean using the homeclaw gateway API."""
import sqlite3
import json
import time
import sys
import urllib.request
import urllib.parse
DB_PATH = "/home/kim/homeclaw/.smallclaw/databases/psychotherapy_cases.db"
API_URL = "http://localhost:18789/v1/chat/completions"
def translate_batch(titles, model="exa-one-3.0:free"):
"""Translate a batch of titles using the gateway API."""
prompt = """Translate the following psychology/psychotherapy article titles from English to Korean.
Rules:
- Keep person names in quotes as-is (e.g., "Fran", "Jane", "Tommy")
- Keep acronyms as-is (CBT, DBT, AEDP, OCD, etc.)
- Translate therapy names: Cognitive Behavioral Therapy→인지행동치료, Dialectical Behavior Therapy→변증법적행동치료, Psychodynamic→정신역동, Schema Therapy→도식치료, Exposure Therapy→노출치료, etc.
- Keep the overall meaning and tone professional
- Each line has format: NUMBER|ENGLISH_TITLE
- Return ONLY the translations in format: NUMBER|KOREAN_TITLE
- Do not add any explanations or notes
"""
for id_, title, cat in titles:
prompt += f"{id_}|{title}\n"
data = json.dumps({
"model": model,
"messages": [
{"role": "system", "content": "You are a professional Korean-English translator specializing in psychology and psychotherapy terminology. Translate accurately and naturally."},
{"role": "user", "content": prompt}
],
"temperature": 0.3,
"max_tokens": 4096,
}).encode("utf-8")
req = urllib.request.Request(
API_URL,
data=data,
headers={"Content-Type": "application/json"},
)
try:
with urllib.request.urlopen(req, timeout=120) as resp:
result = json.loads(resp.read().decode("utf-8"))
return result["choices"][0]["message"]["content"]
except Exception as e:
print(f"API error: {e}", file=sys.stderr)
return None
def main():
conn = sqlite3.connect(DB_PATH)
c = conn.cursor()
# Get untranslated titles
c.execute("SELECT id, title_en, category_en FROM cases WHERE title_ko = '' OR title_ko IS NULL ORDER BY id")
rows = c.fetchall()
if not rows:
print("All titles translated!")
return
print(f"Translating {len(rows)} remaining titles...")
batch_size = 20
total_translated = 0
for i in range(0, len(rows), batch_size):
batch = rows[i:i+batch_size]
print(f"\nBatch {i//batch_size + 1}/{(len(rows) + batch_size - 1)//batch_size} ({len(batch)} titles)...")
result = translate_batch(batch)
if not result:
print("Translation failed, skipping batch")
continue
# Parse translations
for line in result.strip().split("\n"):
line = line.strip()
if "|" in line:
parts = line.split("|", 1)
try:
id_ = int(parts[0].strip())
title_ko = parts[1].strip()
# Remove markdown formatting if present
title_ko = title_ko.strip("*").strip()
c.execute("UPDATE cases SET title_ko = ? WHERE id = ?", (title_ko, id_))
total_translated += 1
except (ValueError, IndexError):
print(f" Skipping malformed line: {line}")
continue
conn.commit()
print(f" Translated so far: {total_translated}")
time.sleep(2) # Rate limiting
# Final stats
c.execute("SELECT COUNT(*) FROM cases WHERE title_ko != '' AND title_ko IS NOT NULL")
translated = c.fetchone()[0]
c.execute("SELECT COUNT(*) FROM cases WHERE title_ko = '' OR title_ko IS NULL")
remaining = c.fetchone()[0]
print(f"\nDone! Translated: {translated}, Remaining: {remaining}")
# Sample
print("\n--- Sample translations ---")
c.execute("SELECT title_en, title_ko FROM cases WHERE title_ko != '' AND title_ko IS NOT NULL ORDER BY RANDOM() LIMIT 10")
for row in c.fetchall():
en = row[0][:60]
ko = row[1][:60]
print(f" EN: {en}...")
print(f" KO: {ko}...")
print()
conn.close()
if __name__ == "__main__":
main()