diff --git a/.gitignore b/.gitignore index d8d77c5..efdf772 100644 Binary files a/.gitignore and b/.gitignore differ diff --git a/backend/app/core/config.py b/backend/app/core/config.py index 691793f..00a2569 100644 --- a/backend/app/core/config.py +++ b/backend/app/core/config.py @@ -11,7 +11,7 @@ class Settings(BaseSettings): SUPABASE_SERVICE_KEY: str = "" # Use Service Role Key for backend operations model_config = SettingsConfigDict( - env_file=str(Path(__file__).resolve().parents[2] / ".env"), + env_file=str(Path(__file__).resolve().parents[3] / ".env"), env_file_encoding="utf-8" ) diff --git a/backend/app/core/env_utils.py b/backend/app/core/env_utils.py new file mode 100644 index 0000000..d169fa2 --- /dev/null +++ b/backend/app/core/env_utils.py @@ -0,0 +1,35 @@ +import os +import re +from pathlib import Path + +def parse_gemini_api_keys(env_path: Path) -> list[str]: + """ + Reads active GEMINI_API_KEY assignments from the given .env file. + Only extracts active assignments and strips inline comments and quotes. + Also falls back to os.environ if no keys are found in the file. + """ + api_keys = [] + + if env_path.exists(): + with open(env_path, 'r', encoding='utf-8') as f: + content = f.read() + # Find all variations of GEMINI_API_KEY assignments + matches = re.findall( + r'^\s*GEMINI_API_KEY\s*=\s*(.+?)\s*(?:#.*)?$', + content, + flags=re.MULTILINE, + ) + for m in matches: + # Remove inline comments and strip quotes + m = re.split(r'\s+#', m, 1)[0] + key = m.strip().strip('"').strip("'") + if key and key not in api_keys: + api_keys.append(key) + + # Fallback to os.environ when parsing produced no key or file doesn't exist + if not api_keys: + k = os.getenv("GEMINI_API_KEY") + if k and k not in api_keys: + api_keys.append(k) + + return api_keys diff --git a/backend/app/services/llm.py b/backend/app/services/llm.py index b97af39..c6183b2 100644 --- a/backend/app/services/llm.py +++ b/backend/app/services/llm.py @@ -1,6 +1,10 @@ +import os +import re import threading +from pathlib import Path import google.generativeai as genai from app.core.config import settings +from app.core.env_utils import parse_gemini_api_keys from langchain_core.prompts import PromptTemplate from langchain_google_genai import ChatGoogleGenerativeAI from langchain_core.output_parsers import StrOutputParser @@ -9,25 +13,56 @@ _llm = None _llm_lock = threading.Lock() +def get_all_gemini_keys() -> list[str]: + """Reads active GEMINI_API_KEY assignments from the root .env file.""" + env_path = Path(__file__).resolve().parents[3] / ".env" + keys = parse_gemini_api_keys(env_path) + + # Ensure the one from environment variables/settings is also included + if getattr(settings, "GEMINI_API_KEY", None) and settings.GEMINI_API_KEY not in keys: + keys.insert(0, settings.GEMINI_API_KEY) + + return keys + def get_llm(): global _llm - if not settings.GEMINI_API_KEY: - raise RuntimeError("GEMINI_API_KEY must be configured") - if _llm is None: with _llm_lock: if _llm is None: # Double-checked locking - # Configure Gemini API natively (optional, if native SDK features are needed) - genai.configure(api_key=settings.GEMINI_API_KEY) + keys = get_all_gemini_keys() + + if not keys: + raise RuntimeError("No GEMINI_API_KEY found in .env or environment") - # Configure LangChain model - # TODO: model gemini-2.5-flash will be deprecated by June 17, 2026. Plan migration to gemini-3-flash. - _llm = ChatGoogleGenerativeAI( - model="gemini-3-flash", - google_api_key=settings.GEMINI_API_KEY, + # Configure Gemini API natively with the first key + genai.configure(api_key=keys[0]) + + print(f"Loaded {len(keys)} Gemini API keys for rotation/fallbacks.") + + # Create the primary model + primary_llm = ChatGoogleGenerativeAI( + model="gemini-2.5-flash-lite", + google_api_key=keys[0], temperature=0.7, - max_retries=2 + max_retries=1 ) + + if len(keys) > 1: + # Create fallback models with the other keys + fallback_llms = [ + ChatGoogleGenerativeAI( + model="gemini-2.5-flash-lite", + google_api_key=k, + temperature=0.7, + max_retries=1 + ) + for k in keys[1:] + ] + # LangChain will automatically retry with the next model if one throws an error (e.g. rate limit / quota) + _llm = primary_llm.with_fallbacks(fallback_llms) + else: + _llm = primary_llm + return _llm diff --git a/backend/data/books_mapping.json b/backend/data/books_mapping.json new file mode 100644 index 0000000..7bd9fc8 --- /dev/null +++ b/backend/data/books_mapping.json @@ -0,0 +1,1010 @@ +[ + { + "original_file": "A Budget of Paradoxes Volume I by Augustus De Morgan.txt", + "translated_title": "역설의 예산 1권", + "translated_author": "어거스터스 드 모르간", + "aladin_data": {} + }, + { + "original_file": "A Pickle for the Knowing Ones by Timothy Dexter.txt", + "translated_title": "아는 자들을 위한 곤경", + "translated_author": "티모시 덱스터", + "aladin_data": {} + }, + { + "original_file": "A Treatise of Human Nature by David Hume.txt", + "translated_title": "인간 본성론", + "translated_author": "데이비드 흄", + "aladin_data": { + "title": "인간이란 무엇인가 - 오성 정념 도덕 본성론", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=4359030&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/435/90/coversum/8949705206_1.jpg", + "author": "데이비드 흄 (지은이), 김성숙 (옮긴이)", + "isbn": "9788949705200" + } + }, + { + "original_file": "A Vindication of the Rights of Woman by Mary Wollstonecraft.txt", + "translated_title": "여권 옹호", + "translated_author": "메리 울스턴크래프트", + "aladin_data": { + "title": "여권의 옹호", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=45690064&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/4569/0/coversum/8994054596_1.jpg", + "author": "메리 울스턴크래프트 (지은이), 손영미 (옮긴이)", + "isbn": "9788994054599" + } + }, + { + "original_file": "Also sprach Zarathustra Ein Buch für Alle und Keinen German by Friedrich Wilhelm Nietzsche.txt", + "translated_title": "차라투스트라는 이렇게 말했다", + "translated_author": "프리드리히 니체", + "aladin_data": { + "title": "차라투스트라는 이렇게 말했다", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=454014&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/45/40/coversum/s352934786_1.jpg", + "author": "프리드리히 니체 (지은이), 장희창 (옮긴이)", + "isbn": "9788937460944" + } + }, + { + "original_file": "An Enquiry Concerning Human Understanding by David Hume.txt", + "translated_title": "인간 오성론", + "translated_author": "데이비드 흄", + "aladin_data": {} + }, + { + "original_file": "An Essay Concerning Humane Understanding Volume 1 by John Locke.txt", + "translated_title": "인간 오성론", + "translated_author": "존 로크", + "aladin_data": { + "title": "존 로크의 인간 오성론 읽기", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=90592125&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/9059/21/coversum/k092535101_1.jpg", + "author": "안병웅 (지은이)", + "isbn": "9791185136318" + } + }, + { + "original_file": "Apology by Plato.txt", + "translated_title": "소크라테스의 변명", + "translated_author": "플라톤", + "aladin_data": { + "title": "소크라테스의 변명 - 크리톤 파이돈 향연, 문예교양선서 30", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=224035&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/22/40/coversum/8931003714_3.jpg", + "author": "플라톤 (지은이), 황문수 (옮긴이)", + "isbn": "9788931003710" + } + }, + { + "original_file": "Apology Crito and Phaedo of Socrates by Plato.txt", + "translated_title": "소크라테스의 변론, 크리톤, 파이돈", + "translated_author": "플라톤", + "aladin_data": { + "title": "소크라테스의 변명·크리톤·파이돈·향연 (그리스어 원전 완역본) - 플라톤의 대화편", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=216792703&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/21679/27/coversum/k252636705_1.jpg", + "author": "플라톤 (지은이), 박문재 (옮긴이)", + "isbn": "9791190398039" + } + }, + { + "original_file": "As a man thinketh by James Allen.txt", + "translated_title": "생각하는 대로", + "translated_author": "제임스 앨런", + "aladin_data": { + "title": "제임스 앨런 원인과 결과의 법칙 - 사람은 생각하는 대로 살게 된다", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=345588057&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/34558/80/coversum/k732933167_1.jpg", + "author": "제임스 알렌 (지은이), 박선영 (옮긴이)", + "isbn": "9791171177660" + } + }, + { + "original_file": "Bacons Essays and Wisdom of the Ancients by Francis Bacon.txt", + "translated_title": "베이컨 수상록; 고대인의 지혜", + "translated_author": "프랜시스 베이컨", + "aladin_data": {} + }, + { + "original_file": "Beyond Good and Evil by Friedrich Wilhelm Nietzsche.txt", + "translated_title": "선악의 저편", + "translated_author": "프리드리히 니체", + "aladin_data": { + "title": "선악의 저편", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=174923171&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/17492/31/coversum/8957336117_1.jpg", + "author": "프리드리히 니체 (지은이), 박찬국 (옮긴이)", + "isbn": "9788957336113" + } + }, + { + "original_file": "Ciceros Tusculan Disputations by Marcus Tullius Cicero.txt", + "translated_title": "투스쿨룸 대화", + "translated_author": "마르쿠스 툴리우스 키케로", + "aladin_data": { + "title": "투스쿨룸 대화", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=286336783&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/28633/67/coversum/8957337679_1.jpg", + "author": "마르쿠스 툴리우스 키케로 (지은이), 김남우 (옮긴이)", + "isbn": "9788957337677" + } + }, + { + "original_file": "De Officiis Latin by Marcus Tullius Cicero.txt", + "translated_title": "의무론", + "translated_author": "마르쿠스 툴리우스 키케로", + "aladin_data": { + "title": "키케로의 의무론 - 그의 아들에게 보낸 편지", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=852420&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/85/24/coversum/8930606245_1.jpg", + "author": "마르쿠스 툴리우스 키케로 (지은이), 허승일 (옮긴이)", + "isbn": "9788930606240" + } + }, + { + "original_file": "Democracy and Education An Introduction to the Philosophy of Education by John Dewey.txt", + "translated_title": "민주주의와 교육", + "translated_author": "존 듀이", + "aladin_data": { + "title": "민주주의와 교육", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=922961&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/92/29/coversum/8925400669_2.jpg", + "author": "존 듀이 (지은이), 이홍우 (옮긴이)", + "isbn": "9788925400662" + } + }, + { + "original_file": "Democracy in America Volume 2 by Alexis de Tocqueville.txt", + "translated_title": "미국의 민주주의 2권", + "translated_author": "알렉시 드 토크빌", + "aladin_data": {} + }, + { + "original_file": "Demonology and Devil-lore by Moncure Daniel Conway.txt", + "translated_title": "악마학 및 악마 전승", + "translated_author": "몽큐어 대니얼 콘웨이", + "aladin_data": {} + }, + { + "original_file": "Discourse on the Method of Rightly Conducting Ones Reason and of Seeking Truth in the Sciences by René Descartes.txt", + "translated_title": "방법서설", + "translated_author": "르네 데카르트", + "aladin_data": { + "title": "방법서설 - 이성을 잘 인도하고 학문에서 진리를 찾기 위한", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=347983217&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/34798/32/coversum/k152933225_1.jpg", + "author": "르네 데카르트 (지은이), 이재훈 (옮긴이)", + "isbn": "9791170872443" + } + }, + { + "original_file": "Ecce Homo by Friedrich Wilhelm Nietzsche.txt", + "translated_title": "이 사람을 보라", + "translated_author": "프리드리히 니체", + "aladin_data": { + "title": "이 사람을 보라", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=302356844&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/30235/68/coversum/8957338195_1.jpg", + "author": "프리드리히 니체 (지은이), 박찬국 (옮긴이)", + "isbn": "9788957338193" + } + }, + { + "original_file": "Essays by Ralph Waldo Emerson by Ralph Waldo Emerson.txt", + "translated_title": "에머슨 수상록", + "translated_author": "랠프 월도 에머슨", + "aladin_data": { + "title": "에머슨 수상록", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=100408&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/10/4/coversum/8972432954_2.jpg", + "author": "랄프 왈도 에머슨 (지은이)", + "isbn": "9788972432951" + } + }, + { + "original_file": "Essays of Schopenhauer by Arthur Schopenhauer.txt", + "translated_title": "인생론", + "translated_author": "아르투어 쇼펜하우어", + "aladin_data": { + "title": "쇼펜하우어의 행복론과 인생론", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=308665960&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/30866/59/coversum/8932440093_1.jpg", + "author": "아르투어 쇼펜하우어 (지은이), 홍성광 (옮긴이)", + "isbn": "9788932440095" + } + }, + { + "original_file": "Ethics by Benedictus de Spinoza.txt", + "translated_title": "에티카", + "translated_author": "베네딕투스 데 스피노자", + "aladin_data": { + "title": "에티카 - 개정판", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=993377&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/99/33/coversum/8930625460_2.jpg", + "author": "베네딕투스 데 스피노자 (지은이), 강영계 (옮긴이)", + "isbn": "9788930625463" + } + }, + { + "original_file": "Etiquette by Emily Post.txt", + "translated_title": "에밀리 포스트의 에티켓", + "translated_author": "에밀리 포스트", + "aladin_data": {} + }, + { + "original_file": "Euthyphro by Plato.txt", + "translated_title": "에우티프론", + "translated_author": "플라톤", + "aladin_data": { + "title": "에우튀프론", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=272171162&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/27217/11/coversum/8957337342_1.jpg", + "author": "플라톤 (지은이), 강성훈 (옮긴이)", + "isbn": "9788957337349" + } + }, + { + "original_file": "Fundamental Principles of the Metaphysic of Morals by Immanuel Kant.txt", + "translated_title": "윤리 형이상학 정초", + "translated_author": "임마누엘 칸트", + "aladin_data": { + "title": "윤리형이상학 정초 - 개정2판", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=168355651&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/16835/56/coversum/8957336036_1.jpg", + "author": "임마누엘 칸트 (지은이), 백종현 (옮긴이)", + "isbn": "9788957336038" + } + }, + { + "original_file": "Goethes Theory of Colours by Johann Wolfgang von Goethe.txt", + "translated_title": "괴테의 색채론", + "translated_author": "요한 볼프강 폰 괴테", + "aladin_data": {} + }, + { + "original_file": "Gorgias by Plato.txt", + "translated_title": "고르기아스", + "translated_author": "플라톤", + "aladin_data": { + "title": "고르기아스", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=265344583&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/26534/45/coversum/8957337210_1.jpg", + "author": "플라톤 (지은이), 김인곤 (옮긴이)", + "isbn": "9788957337219" + } + }, + { + "original_file": "How We Think by John Dewey.txt", + "translated_title": "우리는 어떻게 생각하는가", + "translated_author": "존 듀이", + "aladin_data": {} + }, + { + "original_file": "Human All Too Human A Book for Free Spirits by Friedrich Wilhelm Nietzsche.txt", + "translated_title": "인간적인, 너무나 인간적인", + "translated_author": "프리드리히 니체", + "aladin_data": { + "title": "인간적인 너무나 인간적인 1", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=279599&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/27/95/coversum/8970132619_3.jpg", + "author": "프리드리히 니체 (지은이), 김미기 (옮긴이)", + "isbn": "9788970132617" + } + }, + { + "original_file": "Isis unveiled Volume 1 of 2 Science A master-key to mysteries of ancient and modern science and theology by H P Blavatsky.txt", + "translated_title": "베일 벗은 이시스", + "translated_author": "헬레나 블라바츠키", + "aladin_data": {} + }, + { + "original_file": "Laws by Plato.txt", + "translated_title": "법률", + "translated_author": "플라톤", + "aladin_data": { + "title": "플라톤의 법률", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=4646467&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/464/64/coversum/8930606296_1.jpg", + "author": "플라톤 (지은이), 박종현 (옮긴이)", + "isbn": "9788930606295" + } + }, + { + "original_file": "Leviathan by Thomas Hobbes.txt", + "translated_title": "리바이어던", + "translated_author": "토마스 홉스", + "aladin_data": { + "title": "리바이어던 1 - 교회국가 및 시민국가의 재료와 형태 및 권력", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=2480851&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/248/8/coversum/s392037901_2.jpg", + "author": "토마스 홉스 (지은이), 진석용 (옮긴이)", + "isbn": "9788930083379" + } + }, + { + "original_file": "Meditations by Emperor of Rome Marcus Aurelius.txt", + "translated_title": "명상록", + "translated_author": "마르쿠스 아우렐리우스", + "aladin_data": { + "title": "명상록 - 삶과 죽음을 고뇌한 어느 철학자 황제의 가장 사적인 기록", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=384592083&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/38459/20/coversum/k062135812_1.jpg", + "author": "마르쿠스 아우렐리우스 (지은이), 정미화 (옮긴이), 그레고리 헤이스 (해제)", + "isbn": "9791168273993" + } + }, + { + "original_file": "Nature by Ralph Waldo Emerson.txt", + "translated_title": "자연", + "translated_author": "랄프 왈도 에머슨", + "aladin_data": { + "title": "랄프 왈도 에머슨 : 자연", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=39251790&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/3925/17/coversum/8956607648_1.jpg", + "author": "랄프 왈도 에머슨 (지은이), 서동석 (옮긴이)", + "isbn": "9788956607641" + } + }, + { + "original_file": "On Heroes Hero-Worship and the Heroic in History by Thomas Carlyle.txt", + "translated_title": "영웅숭배론", + "translated_author": "토마스 칼라일", + "aladin_data": { + "title": "영웅숭배론", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=313531822&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/31353/18/coversum/8935678147_1.jpg", + "author": "토머스 칼라일 (지은이), 박상익 (옮긴이)", + "isbn": "9788935678143" + } + }, + { + "original_file": "On Liberty by John Stuart Mill.txt", + "translated_title": "자유론", + "translated_author": "존 스튜어트 밀", + "aladin_data": { + "title": "초판본 자유론 - 1859년 오리지널 초판본 표지 디자인", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=381938135&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/38193/81/coversum/k302034718_1.jpg", + "author": "존 스튜어트 밀 (지은이), 김희상 (옮긴이)", + "isbn": "9791175241961" + } + }, + { + "original_file": "On the Duty of Civil Disobedience by Henry David Thoreau.txt", + "translated_title": "시민 불복종", + "translated_author": "헨리 데이비드 소로", + "aladin_data": { + "title": "월든·시민 불복종 (합본 완역본)", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=284194464&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/28419/44/coversum/k742835213_1.jpg", + "author": "헨리 데이비드 소로 (지은이), 이종인 (옮긴이), 허버트 웬델 글리슨 (사진)", + "isbn": "9791139700503" + } + }, + { + "original_file": "On the Nature of Things by Titus Lucretius Carus.txt", + "translated_title": "사물의 본성에 관하여", + "translated_author": "루크레티우스", + "aladin_data": { + "title": "사물의 본성에 관하여", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=14599483&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/1459/94/coversum/8957332227_1.jpg", + "author": "루크레티우스 (지은이), 강대진 (옮긴이)", + "isbn": "9788957332221" + } + }, + { + "original_file": "On War by Carl von Clausewitz.txt", + "translated_title": "전쟁론", + "translated_author": "카를 폰 클라우제비츠", + "aladin_data": { + "title": "전쟁론 - 전면완역개정판", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=86524117&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/8652/41/coversum/8961951424_1.jpg", + "author": "카알 폰 클라우제비츠 (지은이), 김만수 (옮긴이)", + "isbn": "9788961951425" + } + }, + { + "original_file": "Pascals Pensées by Blaise Pascal.txt", + "translated_title": "파스칼의 팡세", + "translated_author": "블레즈 파스칼", + "aladin_data": { + "title": "파스칼의 팡세", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=367576319&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/36757/63/coversum/k952030294_1.jpg", + "author": "블레즈 파스칼 (지은이), 강현규 (엮은이), 이선미 (옮긴이)", + "isbn": "9791160029529" + } + }, + { + "original_file": "Perpetual Peace A Philosophical Essay by Immanuel Kant.txt", + "translated_title": "영구 평화론", + "translated_author": "임마누엘 칸트", + "aladin_data": { + "title": "영구 평화론 - 하나의 철학적 기획, 개정판", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=2881780&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/288/17/coversum/8930610439_1.jpg", + "author": "임마누엘 칸트 (지은이), 이한구 (옮긴이)", + "isbn": "9788930610438" + } + }, + { + "original_file": "Phaedo by Plato.txt", + "translated_title": "파이돈", + "translated_author": "플라톤", + "aladin_data": { + "title": "소크라테스의 변명·크리톤·파이돈·향연 (그리스어 원전 완역본) - 플라톤의 대화편", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=216792703&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/21679/27/coversum/k252636705_1.jpg", + "author": "플라톤 (지은이), 박문재 (옮긴이)", + "isbn": "9791190398039" + } + }, + { + "original_file": "Phaedrus by Plato.txt", + "translated_title": "파이드로스", + "translated_author": "플라톤", + "aladin_data": { + "title": "파이드로스 - 그리스어 원전 번역판", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=1820615&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/182/6/coversum/8931005881_2.jpg", + "author": "플라톤 (지은이), 조대호 (옮긴이)", + "isbn": "9788931005882" + } + }, + { + "original_file": "Plato and the Other Companions of Sokrates 3rd ed Volume 1 by George Grote.txt", + "translated_title": "플라톤과 소크라테스의 동반자들", + "translated_author": "조지 그로트", + "aladin_data": {} + }, + { + "original_file": "Plutarchs Morals by Plutarch.txt", + "translated_title": "플루타르코스 영웅전", + "translated_author": "플루타르코스", + "aladin_data": { + "title": "플루타르코스 영웅전", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=6970308&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/697/3/coversum/8991290337_2.jpg", + "author": "플루타르코스 (지은이), 천병희 (옮긴이)", + "isbn": "9788991290334" + } + }, + { + "original_file": "Politics A Treatise on Government by Aristotle.txt", + "translated_title": "정치학", + "translated_author": "아리스토텔레스", + "aladin_data": { + "title": "정치학", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=4399813&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/439/98/coversum/8991290280_1.jpg", + "author": "아리스토텔레스 (지은이), 천병희 (옮긴이)", + "isbn": "9788991290280" + } + }, + { + "original_file": "Pragmatism A New Name for Some Old Ways of Thinking by William James.txt", + "translated_title": "실용주의: 어떤 오래된 사고방식에 대한 새로운 이름", + "translated_author": "윌리엄 제임스", + "aladin_data": {} + }, + { + "original_file": "Psyche The Cult of Souls and Belief in Immortality among the Greeks by Erwin Rohde.txt", + "translated_title": "그리스 정신사: 영혼 숭배와 불멸에 대한 신념", + "translated_author": "에르빈 로데", + "aladin_data": {} + }, + { + "original_file": "Psychology of the Unconscious by C G Jung.txt", + "translated_title": "무의식의 심리학", + "translated_author": "카를 구스타프 융", + "aladin_data": { + "title": "칼 융 무의식의 심리학", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=300205010&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/30020/50/coversum/k222838355_1.jpg", + "author": "칼 구스타프 융 (지은이), 정명진 (옮긴이)", + "isbn": "9791159201479" + } + }, + { + "original_file": "Reflections or Sentences and Moral Maxims by François duc de La Rochefoucauld.txt", + "translated_title": "잠언과 도덕적 격언", + "translated_author": "라 로슈푸코 공작", + "aladin_data": {} + }, + { + "original_file": "Revelations of Divine Love by of Norwich Julian.txt", + "translated_title": "신의 사랑에 대한 계시", + "translated_author": "노리치의 줄리안", + "aladin_data": {} + }, + { + "original_file": "Roman Stoicism by Edward Vernon Arnold.txt", + "translated_title": "로마 스토아주의", + "translated_author": "에드워드 버논 아놀드", + "aladin_data": {} + }, + { + "original_file": "Second Treatise of Government by John Locke.txt", + "translated_title": "통치론", + "translated_author": "존 로크", + "aladin_data": { + "title": "통치론 - 시민정부의 참된 기원, 범위 및 그 목적에 관한 시론", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=301106377&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/30110/63/coversum/897291780x_1.jpg", + "author": "존 로크 (지은이), 강정인, 문지영 (옮긴이)", + "isbn": "9788972917809" + } + }, + { + "original_file": "Siddhartha by Hermann Hesse.txt", + "translated_title": "싯다르타", + "translated_author": "헤르만 헤세", + "aladin_data": { + "title": "싯다르타", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=329596&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/32/95/coversum/s062934786_1.jpg", + "author": "헤르만 헤세 (지은이), 박병덕 (옮긴이)", + "isbn": "9788937460586" + } + }, + { + "original_file": "Sun Tzŭ on the Art of War The Oldest Military Treatise in the World by active 6th century BC Sunzi.txt", + "translated_title": "손자병법", + "translated_author": "손무", + "aladin_data": { + "title": "손자병법 - 이겨놓고 싸우는 인생의 지혜", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=372980631&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/37298/6/coversum/k292031545_1.jpg", + "author": "손무 (지은이), 소준섭 (옮긴이)", + "isbn": "9791139728002" + } + }, + { + "original_file": "Symposium by Plato.txt", + "translated_title": "향연", + "translated_author": "플라톤", + "aladin_data": { + "title": "소크라테스의 변명·크리톤·파이돈·향연 (그리스어 원전 완역본) - 플라톤의 대화편", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=216792703&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/21679/27/coversum/k252636705_1.jpg", + "author": "플라톤 (지은이), 박문재 (옮긴이)", + "isbn": "9791190398039" + } + }, + { + "original_file": "The Anatomy of Melancholy by Robert Burton.txt", + "translated_title": "우울의 해부", + "translated_author": "로버트 버튼", + "aladin_data": {} + }, + { + "original_file": "The Antichrist by Friedrich Wilhelm Nietzsche.txt", + "translated_title": "안티크리스트", + "translated_author": "프리드리히 빌헬름 니체", + "aladin_data": { + "title": "안티크리스트", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=35425033&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/3542/50/coversum/8957333444_1.jpg", + "author": "프리드리히 니체 (지은이), 박찬국 (옮긴이)", + "isbn": "9788957333440" + } + }, + { + "original_file": "The Birth of Tragedy or Hellenism and Pessimism by Friedrich Wilhelm Nietzsche.txt", + "translated_title": "비극의 탄생", + "translated_author": "프리드리히 빌헬름 니체", + "aladin_data": { + "title": "비극의 탄생", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=988511&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/98/85/coversum/8957331077_1.jpg", + "author": "프리드리히 니체 (지은이), 박찬국 (옮긴이)", + "isbn": "9788957331071" + } + }, + { + "original_file": "The Case of Wagner Nietzsche Contra Wagner and Selected Aphorisms by Friedrich Wilhelm Nietzsche.txt", + "translated_title": "우상의 황혼", + "translated_author": "프리드리히 니체", + "aladin_data": { + "title": "우상의 황혼", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=64193963&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/6419/39/coversum/8957334513_1.jpg", + "author": "프리드리히 니체 (지은이), 박찬국 (옮긴이)", + "isbn": "9788957334515" + } + }, + { + "original_file": "The City of God Volume I by Saint of Hippo Augustine.txt", + "translated_title": "신의 도시 1", + "translated_author": "히포의 아우구스티누스", + "aladin_data": {} + }, + { + "original_file": "The City of God Volume II by Saint of Hippo Augustine.txt", + "translated_title": "신의 도성 2", + "translated_author": "히포의 아우구스티누스", + "aladin_data": {} + }, + { + "original_file": "The Communist Manifesto by Karl Marx and Friedrich Engels.txt", + "translated_title": "공산당 선언", + "translated_author": "카를 마르크스, 프리드리히 엥겔스", + "aladin_data": { + "title": "공산당 선언", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=143257420&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/14325/74/coversum/k172532941_1.jpg", + "author": "카를 마르크스, 프리드리히 엥겔스 (지은이), 심철민 (옮긴이)", + "isbn": "9791187036548" + } + }, + { + "original_file": "The Confessions of St Augustine by Saint of Hippo Augustine.txt", + "translated_title": "고백록", + "translated_author": "히포의 아우구스티누스", + "aladin_data": {} + }, + { + "original_file": "The Consolation of Philosophy by Boethius.txt", + "translated_title": "철학의 위안", + "translated_author": "보에티우스", + "aladin_data": { + "title": "철학의 위안 - 완역본", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=147121964&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/14712/19/coversum/k002532053_2.jpg", + "author": "아니키우스 보이티우스 (지은이), 박문재 (옮긴이)", + "isbn": "9791187142430" + } + }, + { + "original_file": "The Critique of Pure Reason by Immanuel Kant.txt", + "translated_title": "순수이성비판", + "translated_author": "이마누엘 칸트", + "aladin_data": { + "title": "순수이성비판 1", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=669748&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/66/97/coversum/8957330836_1.jpg", + "author": "임마누엘 칸트 (지은이), 백종현 (옮긴이)", + "isbn": "9788957330838" + } + }, + { + "original_file": "The Enchiridion by Epictetus.txt", + "translated_title": "편람", + "translated_author": "에픽테토스", + "aladin_data": { + "title": "[POD] 에픽테토스 편람 (스토아 사상 철학자) : The Enchiridion (영어원서)", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=231320657&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/23132/6/coversum/k022637708_1.jpg", + "author": "에픽테토스 (지은이)", + "isbn": "9791127295479" + } + }, + { + "original_file": "The Essays of Arthur Schopenhauer Studies in Pessimism by Arthur Schopenhauer.txt", + "translated_title": "쇼펜하우어 철학 에세이: 비관주의 연구", + "translated_author": "아르투어 쇼펜하우어", + "aladin_data": {} + }, + { + "original_file": "The Essays of Arthur Schopenhauer the Wisdom of Life by Arthur Schopenhauer.txt", + "translated_title": "행복론", + "translated_author": "아르투어 쇼펜하우어", + "aladin_data": { + "title": "쇼펜하우어의 행복론과 인생론", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=308665960&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/30866/59/coversum/8932440093_1.jpg", + "author": "아르투어 쇼펜하우어 (지은이), 홍성광 (옮긴이)", + "isbn": "9788932440095" + } + }, + { + "original_file": "The Ethics of Aristotle by Aristotle.txt", + "translated_title": "니코마코스 윤리학", + "translated_author": "아리스토텔레스", + "aladin_data": { + "title": "니코마코스 윤리학 - 그리스어 원전 번역, 개정판", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=31685631&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/3168/56/coversum/8991290523_3.jpg", + "author": "아리스토텔레스 (지은이), 천병희 (옮긴이)", + "isbn": "9788991290525" + } + }, + { + "original_file": "The Genealogy of Morals by Friedrich Wilhelm Nietzsche.txt", + "translated_title": "도덕의 계보", + "translated_author": "프리드리히 니체", + "aladin_data": { + "title": "도덕의 계보", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=274647853&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/27464/78/coversum/8957337350_1.jpg", + "author": "프리드리히 니체 (지은이), 박찬국 (옮긴이)", + "isbn": "9788957337356" + } + }, + { + "original_file": "The Grand Inquisitor by Fyodor Dostoyevsky.txt", + "translated_title": "대심문관", + "translated_author": "표도르 도스토옙스키", + "aladin_data": {} + }, + { + "original_file": "The history of magic including a clear and precise exposition of its procedure its rites and its mysteries by Éliphas Lévi.txt", + "translated_title": "마법의 역사", + "translated_author": "엘리파스 레비", + "aladin_data": {} + }, + { + "original_file": "The Kama Sutra of Vatsyayana by Vatsyayana.txt", + "translated_title": "카마수트라", + "translated_author": "밧사이아나", + "aladin_data": {} + }, + { + "original_file": "The Lives and Opinions of Eminent Philosophers by Diogenes Laertius.txt", + "translated_title": "위대한 철학자들의 생애와 사상", + "translated_author": "디오게네스 라에르티오스", + "aladin_data": {} + }, + { + "original_file": "The Man Who Was Thursday A Nightmare by G K Chesterton.txt", + "translated_title": "목요일의 사나이", + "translated_author": "G. K. 체스터턴", + "aladin_data": {} + }, + { + "original_file": "The Marriage of Heaven and Hell by William Blake.txt", + "translated_title": "천국과 지옥의 결혼", + "translated_author": "윌리엄 블레이크", + "aladin_data": { + "title": "천국과 지옥의 결혼", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=141182&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/14/11/coversum/8937418460_2.jpg", + "author": "윌리엄 블레이크 (지은이), 김종철 (옮긴이)", + "isbn": "9788937418464" + } + }, + { + "original_file": "The Meditations of the Emperor Marcus Aurelius Antoninus by Emperor of Rome Marcus Aurelius.txt", + "translated_title": "마르쿠스 아우렐리우스 황제의 명상록", + "translated_author": "마르쿠스 아우렐리우스", + "aladin_data": { + "title": "명상록 - 삶과 죽음을 고뇌한 어느 철학자 황제의 가장 사적인 기록", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=384592083&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/38459/20/coversum/k062135812_1.jpg", + "author": "마르쿠스 아우렐리우스 (지은이), 정미화 (옮긴이), 그레고리 헤이스 (해제)", + "isbn": "9791168273993" + } + }, + { + "original_file": "The Poetics of Aristotle by Aristotle.txt", + "translated_title": "시학", + "translated_author": "아리스토텔레스", + "aladin_data": { + "title": "아리스토텔레스 시학 (그리스어 원전 완역본)", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=265596201&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/26559/62/coversum/k392738937_1.jpg", + "author": "아리스토텔레스 (지은이), 박문재 (옮긴이)", + "isbn": "9791166812453" + } + }, + { + "original_file": "The Prince by Niccolò Machiavelli.txt", + "translated_title": "군주론", + "translated_author": "니콜로 마키아벨리", + "aladin_data": { + "title": "초판본 군주론 - 오리지널 초판본 표지디자인", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=249432298&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/24943/22/coversum/k032632692_2.jpg", + "author": "니콜로 마키아벨리 (지은이), 이시연 (옮긴이)", + "isbn": "9791164453085" + } + }, + { + "original_file": "The Principles of Psychology Volume 1 of 2 by William James.txt", + "translated_title": "심리학의 원리 제1권", + "translated_author": "윌리엄 제임스", + "aladin_data": {} + }, + { + "original_file": "The Problems of Philosophy by Bertrand Russell.txt", + "translated_title": "철학의 문제들", + "translated_author": "버트런드 러셀", + "aladin_data": { + "title": "철학의 문제들 - 전면 개역판", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=385198660&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/38519/86/coversum/8961474928_1.jpg", + "author": "버트런드 러셀 (지은이), 박영태 (옮긴이)", + "isbn": "9788961474924" + } + }, + { + "original_file": "The Prophet by Kahlil Gibran.txt", + "translated_title": "예언자", + "translated_author": "칼릴 지브란", + "aladin_data": { + "title": "예언자", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=129499645&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/12949/96/coversum/k672532485_1.jpg", + "author": "칼릴 지브란 (지은이), 류시화 (옮긴이)", + "isbn": "9791186686294" + } + }, + { + "original_file": "The Republic by Plato.txt", + "translated_title": "국가", + "translated_author": "플라톤", + "aladin_data": { + "title": "플라톤의 국가·정체(政體) - 개정 증보판", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=16812&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/1/68/coversum/8930606237_2.jpg", + "author": "플라톤 (지은이), 박종현 (옮긴이)", + "isbn": "9788930606233" + } + }, + { + "original_file": "The Republic of Plato by Plato.txt", + "translated_title": "국가", + "translated_author": "플라톤", + "aladin_data": { + "title": "플라톤의 국가·정체(政體) - 개정 증보판", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=16812&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/1/68/coversum/8930606237_2.jpg", + "author": "플라톤 (지은이), 박종현 (옮긴이)", + "isbn": "9788930606233" + } + }, + { + "original_file": "The Secret Doctrine Vol 1 of 4 by H P Blavatsky.txt", + "translated_title": "비밀 교리 1권", + "translated_author": "헬레나 페트로브나 블라바츠키", + "aladin_data": {} + }, + { + "original_file": "The Secret Doctrine Vol 2 of 4 by H P Blavatsky.txt", + "translated_title": "비밀 교리 제2권", + "translated_author": "헬레나 페트로브나 블라바츠키", + "aladin_data": {} + }, + { + "original_file": "The social contract discourses by Jean-Jacques Rousseau.txt", + "translated_title": "사회 계약론", + "translated_author": "장 자크 루소", + "aladin_data": { + "title": "사회계약론 - 자유와 평등을 위한 약속", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=139172090&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/13917/20/coversum/8961672398_1.jpg", + "author": "장 자크 루소 (지은이), 권혁 (옮긴이)", + "isbn": "9788961672399" + } + }, + { + "original_file": "The Song Celestial Or Bhagavad-Gîtâ from the Mahâbhârata.txt", + "translated_title": "신성한 노래", + "translated_author": "바가바드 기타", + "aladin_data": {} + }, + { + "original_file": "The symbolism of Freemasonry Illustrating and explaining its science and philosophy its legends myths and symbols by Albert Gallatin Mackey.txt", + "translated_title": "프리메이슨 상징학", + "translated_author": "앨버트 갤러틴 맥키", + "aladin_data": {} + }, + { + "original_file": "The Twilight of the Idols or How to Philosophize with the Hammer The Antichrist by Friedrich Wilhelm Nietzsche.txt", + "translated_title": "우상의 황혼, 혹은 망치로 철학하기 : 안티크리스트", + "translated_author": "프리드리히 빌헬름 니체", + "aladin_data": {} + }, + { + "original_file": "The Will to Believe and Other Essays in Popular Philosophy by William James.txt", + "translated_title": "의지의 힘", + "translated_author": "윌리엄 제임스", + "aladin_data": {} + }, + { + "original_file": "The World as Will and Idea Vol 1 of 3 by Arthur Schopenhauer.txt", + "translated_title": "의지와 표상으로서의 세계 1", + "translated_author": "아르투어 쇼펜하우어", + "aladin_data": { + "title": "의지와 표상으로서의 세계", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=95607072&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/9560/70/coversum/8949714221_2.jpg", + "author": "아르투어 쇼펜하우어 (지은이), 권기철 (옮긴이)", + "isbn": "9788949714226" + } + }, + { + "original_file": "Thus Spake Zarathustra A Book for All and None by Friedrich Wilhelm Nietzsche.txt", + "translated_title": "차라투스트라는 이렇게 말했다", + "translated_author": "프리드리히 니체", + "aladin_data": { + "title": "차라투스트라는 이렇게 말했다", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=454014&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/45/40/coversum/s352934786_1.jpg", + "author": "프리드리히 니체 (지은이), 장희창 (옮긴이)", + "isbn": "9788937460944" + } + }, + { + "original_file": "Utilitarianism by John Stuart Mill.txt", + "translated_title": "공리주의", + "translated_author": "존 스튜어트 밀", + "aladin_data": { + "title": "공리주의", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=243048009&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/24304/80/coversum/k452630592_1.jpg", + "author": "존 스튜어트 밀 (지은이), 이종인 (옮긴이)", + "isbn": "9791190878142" + } + }, + { + "original_file": "Utopia by Saint Thomas More.txt", + "translated_title": "유토피아", + "translated_author": "토머스 모어", + "aladin_data": { + "title": "유토피아", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=565805&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/56/58/coversum/8974832534_1.jpg", + "author": "토머스 모어 (지은이), 나종일 (옮긴이)", + "isbn": "9788974832537" + } + }, + { + "original_file": "Walden and On The Duty Of Civil Disobedience by Henry David Thoreau.txt", + "translated_title": "월든", + "translated_author": "헨리 데이비드 소로", + "aladin_data": { + "title": "월든 - 완결판", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=12840843&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/1284/8/coversum/8956605416_3.jpg", + "author": "헨리 데이비드 소로 (지은이), 강승영 (옮긴이)", + "isbn": "9788956605418" + } + }, + { + "original_file": "What Is Art by graf Leo Tolstoy.txt", + "translated_title": "예술이란 무엇인가", + "translated_author": "레프 톨스토이", + "aladin_data": { + "title": "예술이란 무엇인가", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=319767632&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/31976/76/coversum/k312834367_1.jpg", + "author": "레프 니콜라예비치 톨스토이 (지은이), 이강은 (옮긴이)", + "isbn": "9791166891694" + } + }, + { + "original_file": "新序 Chinese by Xiang Liu.txt", + "translated_title": "신서", + "translated_author": "유향", + "aladin_data": { + "title": "신서 1", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=6171917&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/617/19/coversum/8949705818_1.jpg", + "author": "유향 (지은이), 임동석 (옮긴이)", + "isbn": "9788949705811" + } + }, + { + "original_file": "日知錄 Chinese by Yanwu Gu.txt", + "translated_title": "일지록", + "translated_author": "고염무", + "aladin_data": { + "title": "원서발췌 일지록", + "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=383905503&partner=openAPI&start=api", + "thumbnail": "https://image.aladin.co.kr/product/38390/55/coversum/k522135566_1.jpg", + "author": "고염무 (지은이), 윤대식 (옮긴이)", + "isbn": "9791143017086" + } + }, + { + "original_file": "韓詩外傳 Complete Chinese by active 150 BC Ying Han.txt", + "translated_title": "한시외전", + "translated_author": "영한", + "aladin_data": {} + } +] \ No newline at end of file diff --git a/backend/scripts/check_models.py b/backend/scripts/check_models.py new file mode 100644 index 0000000..1f8e348 --- /dev/null +++ b/backend/scripts/check_models.py @@ -0,0 +1,29 @@ +import os +from pathlib import Path +from dotenv import load_dotenv +import google.generativeai as genai + +env_path = Path(__file__).resolve().parents[2] / ".env" +load_dotenv(dotenv_path=env_path) + +import sys + +def main() -> int: + api_key = os.getenv("GEMINI_API_KEY") + if not api_key: + print("No API key found!") + return 1 + + genai.configure(api_key=api_key) + print("Available Models:") + try: + for m in genai.list_models(): + if 'generateContent' in m.supported_generation_methods: + print(m.name) + except Exception as e: + print(f"Error listing models: {e}") + return 1 + return 0 + +if __name__ == "__main__": + sys.exit(main()) diff --git a/backend/scripts/generate_book_mapping.py b/backend/scripts/generate_book_mapping.py new file mode 100644 index 0000000..6af9e45 --- /dev/null +++ b/backend/scripts/generate_book_mapping.py @@ -0,0 +1,214 @@ +import os +import re +import json +import asyncio +import sys +from pathlib import Path +from dotenv import load_dotenv +import urllib.request +import urllib.parse +import urllib.error +import google.generativeai as genai +from google.api_core.exceptions import ResourceExhausted + +backend_dir = Path(__file__).resolve().parents[1] +if str(backend_dir) not in sys.path: + sys.path.insert(0, str(backend_dir)) + +from app.core.env_utils import parse_gemini_api_keys + +env_path = backend_dir.parent / ".env" +print(f"Loading .env from {env_path}, exists: {env_path.exists()}") +load_dotenv(dotenv_path=env_path) + +# Extract ALL GEMINI_API_KEYs from .env file +api_keys = parse_gemini_api_keys(env_path) + +# The user explicitly asked to start testing from new keys (lines 8~14), and then go back to line 2. +# Rotates keys only when running with ENABLE_TEST_KEY_ROTATION flag. +if os.getenv("ENABLE_TEST_KEY_ROTATION") and len(api_keys) >= 4: + api_keys = api_keys[3:] + api_keys[:3] + +current_key_idx = 0 + +DATA_DIR = backend_dir / "data" +MAPPING_FILE = backend_dir / "data" / "books_mapping.json" +ALADIN_API_KEY = os.getenv("ALADIN_API_KEY") + +prompt_template = """You are given an English file name representing a philosophical book and its author. +Your task is to provide the standard, most well-known Korean translation title for this book, and the author's name in Korean. +Return ONLY JSON format exactly like this, without any markdown formatting or explanations: +{{"title": "한국어 번역본 책 제목", "author": "한국어 저자 이름"}} + +File name: {file_name} +""" + +async def kyobo_fallback(title: str, author: str) -> dict: + clean_title = title.replace(".txt", "").replace("_", " ") + query = f"{clean_title}".strip() + encoded_query = urllib.parse.quote(query) + url = f"https://search.kyobobook.co.kr/search?keyword={encoded_query}" + + req = urllib.request.Request(url, headers={'User-Agent': 'Mozilla/5.0'}) + + loop = asyncio.get_running_loop() + def fetch(): + try: + with urllib.request.urlopen(req, timeout=10) as response: + return response.read().decode('utf-8') + except urllib.error.URLError as e: + print(f"Kyobo network error: {e}") + return None + except Exception as e: + print(f"Kyobo undefined error: {e}") + raise + + html = await loop.run_in_executor(None, fetch) + if not html: + return {"kr_title": clean_title, "kr_author": author} + + match = re.search(r'(.*?)', html) + if match: + kr_title = match.group(1).strip() + kr_title = re.sub(r'<[^>]+>', '', kr_title) # Remove internal tags + return {"kr_title": kr_title, "kr_author": author} + + return {"kr_title": clean_title, "kr_author": author} + +async def translate_book_info(file_name: str) -> dict: + global current_key_idx + + while current_key_idx < len(api_keys): + key = api_keys[current_key_idx] + genai.configure(api_key=key) + # Using gemini-2.5-flash-lite as it has a higher free tier + model = genai.GenerativeModel("gemini-2.5-flash-lite") + + try: + response = await model.generate_content_async( + prompt_template.format(file_name=file_name), + generation_config=genai.types.GenerationConfig(temperature=0.7) + ) + result_text = response.text + clean_text = result_text.replace("```json", "").replace("```", "").strip() + data = json.loads(clean_text) + return {"kr_title": data["title"], "kr_author": data["author"]} + + except ResourceExhausted: + print(f"API Key {current_key_idx} exhausted. Switching to next key...") + current_key_idx += 1 + except Exception as e: + error_str = str(e).lower() + should_rotate = any( + token in error_str + for token in ( + "429", "quota", "exhausted", "toomanyrequests", + "401", "403", "invalid api key", "permission", "unauthenticated", + ) + ) + if should_rotate: + print(f"API Key {current_key_idx} exhausted/invalid. Switching to next key...") + current_key_idx += 1 + else: + print(f"Failed to parse LLM translation for {file_name}: {e}") + current_key_idx += 1 + + # If all keys exhausted or other error, fallback + print(f"LLM Failed for {file_name}, falling back to Kyobo Search...") + return await kyobo_fallback(file_name, "") + +async def search_aladin(title: str, author: str) -> dict: + if not ALADIN_API_KEY: + print(f"Warning: ALADIN_API_KEY is not set. Skipping search for {title}") + return {} + + query = f"{title} {author}".strip() + url = f"https://www.aladin.co.kr/ttb/api/ItemSearch.aspx?ttbkey={ALADIN_API_KEY}&Query={urllib.parse.quote(query)}&QueryType=Keyword&MaxResults=1&start=1&SearchTarget=Book&output=js&Version=20131101" + + try: + loop = asyncio.get_running_loop() + def fetch(): + with urllib.request.urlopen(url, timeout=10) as response: + return response.read().decode('utf-8') + + response_text = await loop.run_in_executor(None, fetch) + data = json.loads(response_text) + + items = data.get("item", []) + if items: + item = items[0] + return { + "title": item.get("title", ""), + "link": item.get("link", ""), + "thumbnail": item.get("cover", ""), + "author": item.get("author", ""), + "isbn": item.get("isbn13", "") + } + except Exception as e: + print(f"Aladin API Error for {query}: {e}") + + return {} + +async def process_file(file_path: Path): + file_name = file_path.stem + print(f"Processing: {file_name}") + + translated = await translate_book_info(file_name) + kr_title = translated["kr_title"] + kr_author = translated["kr_author"] + + aladin_data = await search_aladin(kr_title, kr_author) + + return { + "original_file": file_path.name, + "translated_title": kr_title, + "translated_author": kr_author, + "aladin_data": aladin_data + } + +async def main(): + if not DATA_DIR.exists(): + print(f"Data directory not found at {DATA_DIR}") + return + + txt_files = list(DATA_DIR.glob("*.txt")) + print(f"Found {len(txt_files)} text files.") + + mapping = [] + if MAPPING_FILE.exists(): + with open(MAPPING_FILE, "r", encoding="utf-8") as f: + try: + mapping = json.load(f) + except json.JSONDecodeError: + mapping = [] + + existing_files = { + item.get("original_file") + for item in mapping + if isinstance(item, dict) and item.get("original_file") + } + files_to_process = [f for f in txt_files if f.name not in existing_files] + + print(f"Skipping {len(existing_files)} already processed files. Processing {len(files_to_process)} new files.") + print(f"Loaded {len(api_keys)} API keys for rotation.") + + for i, f in enumerate(files_to_process): + try: + result = await process_file(f) + mapping.append(result) + + tmp_file = MAPPING_FILE.with_suffix(".json.tmp") + with open(tmp_file, "w", encoding="utf-8") as out_f: + json.dump(mapping, out_f, ensure_ascii=False, indent=4) + tmp_file.replace(MAPPING_FILE) + + print(f"Processed {i + 1}/{len(files_to_process)}, sleeping for 4s...") + await asyncio.sleep(4.1) + except Exception as e: + print(f"Error processing {f.name}: {e}") + await asyncio.sleep(4.1) + + print(f"Finished mapping. Total mapped: {len(mapping)}") + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/backend/scripts/generate_sql_updates.py b/backend/scripts/generate_sql_updates.py new file mode 100644 index 0000000..369c518 --- /dev/null +++ b/backend/scripts/generate_sql_updates.py @@ -0,0 +1,63 @@ +import json +import os +from pathlib import Path + +def generate_sql(): + # Load mapping + backend_dir = Path(__file__).resolve().parents[1] + mapping_path = backend_dir / "data" / "books_mapping.json" + with open(mapping_path, "r", encoding="utf-8") as f: + mapping_data = json.load(f) + + # 1. Create a B-Tree index on the title field to make string matching instant + # instead of doing a full sequential table scan + sql_statements = [ + "BEGIN;\n", + "CREATE INDEX IF NOT EXISTS idx_documents_book_title ON documents ((metadata->'book_info'->>'title'));\n", + "SET statement_timeout = '120s'; -- Increase timeout to be safe\n" + ] + + for book in mapping_data: + original_file = book.get("original_file", "") + name_without_ext = os.path.splitext(original_file)[0] + parts = name_without_ext.rsplit(" by ", 1) + if len(parts) == 2: + title = parts[0].strip() + else: + title = name_without_ext + + title_to_match = f"Korean Translation of {title}" + + kr_title = book.get("translated_title", "") + aladin = book.get("aladin_data", {}) + thumbnail = aladin.get("thumbnail", "") + link = aladin.get("link", "") + + # Escape single quotes in strings for SQL + title_to_match_esc = title_to_match.replace("'", "''") + + jsonb_payload = json.dumps({ + "kr_title": kr_title, + "thumbnail": thumbnail, + "link": link + }, ensure_ascii=False) + + # Double the single quotes inside the json string for the SQL literal + jsonb_payload_esc = jsonb_payload.replace("'", "''") + + sql = f"""UPDATE documents +SET metadata = metadata || '{jsonb_payload_esc}'::jsonb +WHERE metadata->'book_info'->>'title' = '{title_to_match_esc}';""" + + sql_statements.append(sql) + + sql_statements.append("COMMIT;") + + output_path = backend_dir / "update_metadata.sql" + with open(output_path, "w", encoding="utf-8") as f: + f.write("\n\n".join(sql_statements)) + + print(f"Generated {output_path} with {len(sql_statements)} statements (including BEGIN/COMMIT).") + +if __name__ == "__main__": + generate_sql() diff --git a/backend/scripts/update_db_metadata.py b/backend/scripts/update_db_metadata.py new file mode 100644 index 0000000..bd77027 --- /dev/null +++ b/backend/scripts/update_db_metadata.py @@ -0,0 +1,143 @@ +import os +import sys +import json +import asyncio +from pathlib import Path +from dotenv import load_dotenv + +backend_dir = Path(__file__).resolve().parents[1] +if str(backend_dir) not in sys.path: + sys.path.insert(0, str(backend_dir)) + +env_path = backend_dir.parent / ".env" +load_dotenv(dotenv_path=env_path) + +from app.services.database import get_client + +# Load mapping data +MAPPING_FILE = backend_dir / "data" / "books_mapping.json" + +def update_database(): + print(f"Loading mapping from {MAPPING_FILE}") + if not MAPPING_FILE.exists(): + print("Mapping file not found.") + return + + with open(MAPPING_FILE, "r", encoding="utf-8") as f: + try: + mapping_data = json.load(f) + except Exception as e: + print(f"Error reading JSON: {e}") + return + + print(f"Found {len(mapping_data)} mapping entries.") + + supabase = get_client() + + success_count = 0 + error_count = 0 + + print("Fetching all document metadata ids to match locally...") + # Fetching all chunks to match metadata in memory to save DB query overhead/complexity. + # We only need id and metadata explicitly. + try: + # Since we might have many records, we paginate or fetch all + # Assuming < 10000 chunks for 100 books. Let's fetch all in one go or paginate. + all_docs = [] + limit = 1000 + offset = 0 + while True: + res = supabase.table("documents").select("id, metadata").range(offset, offset + limit - 1).execute() + all_docs.extend(res.data) + if len(res.data) < limit: + break + offset += limit + print(f"Total document chunks retrieved: {len(all_docs)}") + + except Exception as e: + print(f"Error fetching from supabase: {e}") + return + + print("\nStarting batch updates...") + + # Pre-process mapping data into a dictionary for quick lookup by 'title_to_match' + mapping_dict = {} + for book in mapping_data: + original_file = book.get("original_file", "") + # Parse filename exactly as ingest_all_data.py did to recreate the title. + name_without_ext = Path(original_file).stem + parts = name_without_ext.rsplit(" by ", 1) + if len(parts) == 2: + title = parts[0].strip() + else: + title = name_without_ext + + # ingest_data.py stores this specific mock title in the DB: + title_to_match = f"Korean Translation of {title}" + mapping_dict[title_to_match] = book + + updates_to_make = [] + + if all_docs: + print("Sample metadata from DB:", all_docs[0]['metadata']) + + for doc in all_docs: + doc_id = doc['id'] + metadata = doc['metadata'] + + # The DB stores the title we want to match inside metadata->book_info->title + db_title = metadata.get('book_info', {}).get('title', '') + + # Determine which mapping record matches this chunk's DB title + matched_book = mapping_dict.get(db_title) + + if matched_book: + kr_title = matched_book.get("translated_title", "") + aladin = matched_book.get("aladin_data", {}) + thumbnail = aladin.get("thumbnail", "") + link = aladin.get("link", "") + + # Check if we actually need to update + if metadata.get("kr_title") != kr_title or metadata.get("thumbnail") != thumbnail or metadata.get("link") != link: + metadata["kr_title"] = kr_title + metadata["thumbnail"] = thumbnail + metadata["link"] = link + updates_to_make.append({"id": doc_id, "metadata": metadata}) + + print(f"Determined {len(updates_to_make)} chunks need metadata updates.") + + # Batch update using concurrent updates + if updates_to_make: + import concurrent.futures + from time import sleep + + def update_doc(doc): + max_retries = 3 + for attempt in range(max_retries): + try: + supabase.table("documents").update({"metadata": doc["metadata"]}).eq("id", doc["id"]).execute() + return True + except Exception as e: + if attempt < max_retries - 1: + sleep(0.5 * (attempt + 1)) # Exponential backoff + continue + print(f"Error updating {doc['id']}: {e}") + return False + + print(f"Starting concurrent updates with 10 workers for {len(updates_to_make)} rows...") + processed = 0 + with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor: + for result in executor.map(update_doc, updates_to_make): + processed += 1 + if result: + success_count += 1 + else: + error_count += 1 + + if processed % 1000 == 0: + print(f"Processed {processed}/{len(updates_to_make)}...") + + print(f"\nUpdate complete! Success: {success_count}, Errors: {error_count}") + +if __name__ == "__main__": + update_database() diff --git a/backend/update_metadata.sql b/backend/update_metadata.sql new file mode 100644 index 0000000..51b2a24 --- /dev/null +++ b/backend/update_metadata.sql @@ -0,0 +1,412 @@ +CREATE INDEX IF NOT EXISTS idx_documents_book_title ON documents ((metadata->'book_info'->>'title')); + + +SET statement_timeout = '120s'; -- Increase timeout to be safe + +BEGIN; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "역설의 예산 1권", "thumbnail": "", "link": ""}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of A Budget of Paradoxes Volume I'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "아는 자들을 위한 곤경", "thumbnail": "", "link": ""}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of A Pickle for the Knowing Ones'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "인간 본성론", "thumbnail": "https://image.aladin.co.kr/product/435/90/coversum/8949705206_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=4359030&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of A Treatise of Human Nature'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "여권 옹호", "thumbnail": "https://image.aladin.co.kr/product/4569/0/coversum/8994054596_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=45690064&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of A Vindication of the Rights of Woman'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "차라투스트라는 이렇게 말했다", "thumbnail": "https://image.aladin.co.kr/product/45/40/coversum/s352934786_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=454014&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Also sprach Zarathustra Ein Buch für Alle und Keinen German'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "인간 오성론", "thumbnail": "", "link": ""}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of An Enquiry Concerning Human Understanding'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "인간 오성론", "thumbnail": "https://image.aladin.co.kr/product/9059/21/coversum/k092535101_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=90592125&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of An Essay Concerning Humane Understanding Volume 1'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "소크라테스의 변명", "thumbnail": "https://image.aladin.co.kr/product/22/40/coversum/8931003714_3.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=224035&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Apology'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "소크라테스의 변론, 크리톤, 파이돈", "thumbnail": "https://image.aladin.co.kr/product/21679/27/coversum/k252636705_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=216792703&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Apology Crito and Phaedo of Socrates'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "생각하는 대로", "thumbnail": "https://image.aladin.co.kr/product/34558/80/coversum/k732933167_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=345588057&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of As a man thinketh'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "베이컨 수상록; 고대인의 지혜", "thumbnail": "", "link": ""}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Bacons Essays and Wisdom of the Ancients'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "선악의 저편", "thumbnail": "https://image.aladin.co.kr/product/17492/31/coversum/8957336117_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=174923171&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Beyond Good and Evil'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "투스쿨룸 대화", "thumbnail": "https://image.aladin.co.kr/product/28633/67/coversum/8957337679_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=286336783&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Ciceros Tusculan Disputations'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "의무론", "thumbnail": "https://image.aladin.co.kr/product/85/24/coversum/8930606245_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=852420&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of De Officiis Latin'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "민주주의와 교육", "thumbnail": "https://image.aladin.co.kr/product/92/29/coversum/8925400669_2.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=922961&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Democracy and Education An Introduction to the Philosophy of Education'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "미국의 민주주의 2권", "thumbnail": "", "link": ""}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Democracy in America Volume 2'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "악마학 및 악마 전승", "thumbnail": "", "link": ""}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Demonology and Devil-lore'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "방법서설", "thumbnail": "https://image.aladin.co.kr/product/34798/32/coversum/k152933225_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=347983217&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Discourse on the Method of Rightly Conducting Ones Reason and of Seeking Truth in the Sciences'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "이 사람을 보라", "thumbnail": "https://image.aladin.co.kr/product/30235/68/coversum/8957338195_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=302356844&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Ecce Homo'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "에머슨 수상록", "thumbnail": "https://image.aladin.co.kr/product/10/4/coversum/8972432954_2.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=100408&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Essays by Ralph Waldo Emerson'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "인생론", "thumbnail": "https://image.aladin.co.kr/product/30866/59/coversum/8932440093_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=308665960&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Essays of Schopenhauer'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "에티카", "thumbnail": "https://image.aladin.co.kr/product/99/33/coversum/8930625460_2.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=993377&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Ethics'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "에밀리 포스트의 에티켓", "thumbnail": "", "link": ""}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Etiquette'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "에우티프론", "thumbnail": "https://image.aladin.co.kr/product/27217/11/coversum/8957337342_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=272171162&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Euthyphro'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "윤리 형이상학 정초", "thumbnail": "https://image.aladin.co.kr/product/16835/56/coversum/8957336036_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=168355651&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Fundamental Principles of the Metaphysic of Morals'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "괴테의 색채론", "thumbnail": "", "link": ""}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Goethes Theory of Colours'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "고르기아스", "thumbnail": "https://image.aladin.co.kr/product/26534/45/coversum/8957337210_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=265344583&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Gorgias'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "우리는 어떻게 생각하는가", "thumbnail": "", "link": ""}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of How We Think'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "인간적인, 너무나 인간적인", "thumbnail": "https://image.aladin.co.kr/product/27/95/coversum/8970132619_3.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=279599&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Human All Too Human A Book for Free Spirits'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "베일 벗은 이시스", "thumbnail": "", "link": ""}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Isis unveiled Volume 1 of 2 Science A master-key to mysteries of ancient and modern science and theology'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "법률", "thumbnail": "https://image.aladin.co.kr/product/464/64/coversum/8930606296_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=4646467&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Laws'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "리바이어던", "thumbnail": "https://image.aladin.co.kr/product/248/8/coversum/s392037901_2.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=2480851&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Leviathan'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "명상록", "thumbnail": "https://image.aladin.co.kr/product/38459/20/coversum/k062135812_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=384592083&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Meditations'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "자연", "thumbnail": "https://image.aladin.co.kr/product/3925/17/coversum/8956607648_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=39251790&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Nature'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "영웅숭배론", "thumbnail": "https://image.aladin.co.kr/product/31353/18/coversum/8935678147_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=313531822&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of On Heroes Hero-Worship and the Heroic in History'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "자유론", "thumbnail": "https://image.aladin.co.kr/product/38193/81/coversum/k302034718_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=381938135&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of On Liberty'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "시민 불복종", "thumbnail": "https://image.aladin.co.kr/product/28419/44/coversum/k742835213_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=284194464&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of On the Duty of Civil Disobedience'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "사물의 본성에 관하여", "thumbnail": "https://image.aladin.co.kr/product/1459/94/coversum/8957332227_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=14599483&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of On the Nature of Things'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "전쟁론", "thumbnail": "https://image.aladin.co.kr/product/8652/41/coversum/8961951424_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=86524117&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of On War'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "파스칼의 팡세", "thumbnail": "https://image.aladin.co.kr/product/36757/63/coversum/k952030294_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=367576319&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Pascals Pensées'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "영구 평화론", "thumbnail": "https://image.aladin.co.kr/product/288/17/coversum/8930610439_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=2881780&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Perpetual Peace A Philosophical Essay'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "파이돈", "thumbnail": "https://image.aladin.co.kr/product/21679/27/coversum/k252636705_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=216792703&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Phaedo'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "파이드로스", "thumbnail": "https://image.aladin.co.kr/product/182/6/coversum/8931005881_2.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=1820615&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Phaedrus'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "플라톤과 소크라테스의 동반자들", "thumbnail": "", "link": ""}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Plato and the Other Companions of Sokrates 3rd ed Volume 1'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "플루타르코스 영웅전", "thumbnail": "https://image.aladin.co.kr/product/697/3/coversum/8991290337_2.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=6970308&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Plutarchs Morals'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "정치학", "thumbnail": "https://image.aladin.co.kr/product/439/98/coversum/8991290280_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=4399813&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Politics A Treatise on Government'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "실용주의: 어떤 오래된 사고방식에 대한 새로운 이름", "thumbnail": "", "link": ""}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Pragmatism A New Name for Some Old Ways of Thinking'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "그리스 정신사: 영혼 숭배와 불멸에 대한 신념", "thumbnail": "", "link": ""}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Psyche The Cult of Souls and Belief in Immortality among the Greeks'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "무의식의 심리학", "thumbnail": "https://image.aladin.co.kr/product/30020/50/coversum/k222838355_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=300205010&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Psychology of the Unconscious'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "잠언과 도덕적 격언", "thumbnail": "", "link": ""}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Reflections or Sentences and Moral Maxims'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "신의 사랑에 대한 계시", "thumbnail": "", "link": ""}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Revelations of Divine Love'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "로마 스토아주의", "thumbnail": "", "link": ""}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Roman Stoicism'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "통치론", "thumbnail": "https://image.aladin.co.kr/product/30110/63/coversum/897291780x_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=301106377&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Second Treatise of Government'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "싯다르타", "thumbnail": "https://image.aladin.co.kr/product/32/95/coversum/s062934786_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=329596&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Siddhartha'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "손자병법", "thumbnail": "https://image.aladin.co.kr/product/37298/6/coversum/k292031545_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=372980631&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Sun Tzŭ on the Art of War The Oldest Military Treatise in the World'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "향연", "thumbnail": "https://image.aladin.co.kr/product/21679/27/coversum/k252636705_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=216792703&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Symposium'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "우울의 해부", "thumbnail": "", "link": ""}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The Anatomy of Melancholy'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "안티크리스트", "thumbnail": "https://image.aladin.co.kr/product/3542/50/coversum/8957333444_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=35425033&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The Antichrist'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "비극의 탄생", "thumbnail": "https://image.aladin.co.kr/product/98/85/coversum/8957331077_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=988511&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The Birth of Tragedy or Hellenism and Pessimism'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "우상의 황혼", "thumbnail": "https://image.aladin.co.kr/product/6419/39/coversum/8957334513_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=64193963&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The Case of Wagner Nietzsche Contra Wagner and Selected Aphorisms'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "신의 도시 1", "thumbnail": "", "link": ""}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The City of God Volume I'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "신의 도성 2", "thumbnail": "", "link": ""}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The City of God Volume II'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "공산당 선언", "thumbnail": "https://image.aladin.co.kr/product/14325/74/coversum/k172532941_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=143257420&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The Communist Manifesto'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "고백록", "thumbnail": "", "link": ""}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The Confessions of St Augustine'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "철학의 위안", "thumbnail": "https://image.aladin.co.kr/product/14712/19/coversum/k002532053_2.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=147121964&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The Consolation of Philosophy'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "순수이성비판", "thumbnail": "https://image.aladin.co.kr/product/66/97/coversum/8957330836_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=669748&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The Critique of Pure Reason'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "편람", "thumbnail": "https://image.aladin.co.kr/product/23132/6/coversum/k022637708_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=231320657&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The Enchiridion'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "쇼펜하우어 철학 에세이: 비관주의 연구", "thumbnail": "", "link": ""}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The Essays of Arthur Schopenhauer Studies in Pessimism'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "행복론", "thumbnail": "https://image.aladin.co.kr/product/30866/59/coversum/8932440093_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=308665960&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The Essays of Arthur Schopenhauer the Wisdom of Life'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "니코마코스 윤리학", "thumbnail": "https://image.aladin.co.kr/product/3168/56/coversum/8991290523_3.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=31685631&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The Ethics of Aristotle'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "도덕의 계보", "thumbnail": "https://image.aladin.co.kr/product/27464/78/coversum/8957337350_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=274647853&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The Genealogy of Morals'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "대심문관", "thumbnail": "", "link": ""}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The Grand Inquisitor'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "마법의 역사", "thumbnail": "", "link": ""}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The history of magic including a clear and precise exposition of its procedure its rites and its mysteries'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "카마수트라", "thumbnail": "", "link": ""}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The Kama Sutra of Vatsyayana'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "위대한 철학자들의 생애와 사상", "thumbnail": "", "link": ""}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The Lives and Opinions of Eminent Philosophers'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "목요일의 사나이", "thumbnail": "", "link": ""}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The Man Who Was Thursday A Nightmare'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "천국과 지옥의 결혼", "thumbnail": "https://image.aladin.co.kr/product/14/11/coversum/8937418460_2.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=141182&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The Marriage of Heaven and Hell'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "마르쿠스 아우렐리우스 황제의 명상록", "thumbnail": "https://image.aladin.co.kr/product/38459/20/coversum/k062135812_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=384592083&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The Meditations of the Emperor Marcus Aurelius Antoninus'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "시학", "thumbnail": "https://image.aladin.co.kr/product/26559/62/coversum/k392738937_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=265596201&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The Poetics of Aristotle'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "군주론", "thumbnail": "https://image.aladin.co.kr/product/24943/22/coversum/k032632692_2.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=249432298&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The Prince'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "심리학의 원리 제1권", "thumbnail": "", "link": ""}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The Principles of Psychology Volume 1 of 2'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "철학의 문제들", "thumbnail": "https://image.aladin.co.kr/product/38519/86/coversum/8961474928_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=385198660&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The Problems of Philosophy'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "예언자", "thumbnail": "https://image.aladin.co.kr/product/12949/96/coversum/k672532485_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=129499645&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The Prophet'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "국가", "thumbnail": "https://image.aladin.co.kr/product/1/68/coversum/8930606237_2.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=16812&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The Republic'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "국가", "thumbnail": "https://image.aladin.co.kr/product/1/68/coversum/8930606237_2.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=16812&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The Republic of Plato'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "비밀 교리 1권", "thumbnail": "", "link": ""}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The Secret Doctrine Vol 1 of 4'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "비밀 교리 제2권", "thumbnail": "", "link": ""}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The Secret Doctrine Vol 2 of 4'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "사회 계약론", "thumbnail": "https://image.aladin.co.kr/product/13917/20/coversum/8961672398_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=139172090&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The social contract discourses'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "신성한 노래", "thumbnail": "", "link": ""}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The Song Celestial Or Bhagavad-Gîtâ from the Mahâbhârata'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "프리메이슨 상징학", "thumbnail": "", "link": ""}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The symbolism of Freemasonry Illustrating and explaining its science and philosophy its legends myths and symbols'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "우상의 황혼, 혹은 망치로 철학하기 : 안티크리스트", "thumbnail": "", "link": ""}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The Twilight of the Idols or How to Philosophize with the Hammer The Antichrist'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "의지의 힘", "thumbnail": "", "link": ""}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The Will to Believe and Other Essays in Popular Philosophy'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "의지와 표상으로서의 세계 1", "thumbnail": "https://image.aladin.co.kr/product/9560/70/coversum/8949714221_2.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=95607072&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of The World as Will and Idea Vol 1 of 3'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "차라투스트라는 이렇게 말했다", "thumbnail": "https://image.aladin.co.kr/product/45/40/coversum/s352934786_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=454014&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Thus Spake Zarathustra A Book for All and None'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "공리주의", "thumbnail": "https://image.aladin.co.kr/product/24304/80/coversum/k452630592_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=243048009&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Utilitarianism'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "유토피아", "thumbnail": "https://image.aladin.co.kr/product/56/58/coversum/8974832534_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=565805&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Utopia'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "월든", "thumbnail": "https://image.aladin.co.kr/product/1284/8/coversum/8956605416_3.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=12840843&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of Walden and On The Duty Of Civil Disobedience'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "예술이란 무엇인가", "thumbnail": "https://image.aladin.co.kr/product/31976/76/coversum/k312834367_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=319767632&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of What Is Art'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "신서", "thumbnail": "https://image.aladin.co.kr/product/617/19/coversum/8949705818_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=6171917&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of 新序 Chinese'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "일지록", "thumbnail": "https://image.aladin.co.kr/product/38390/55/coversum/k522135566_1.jpg", "link": "https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=383905503&partner=openAPI&start=api"}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of 日知錄 Chinese'; + +UPDATE documents +SET metadata = metadata || '{"kr_title": "한시외전", "thumbnail": "", "link": ""}'::jsonb +WHERE metadata->'book_info'->>'title' = 'Korean Translation of 韓詩外傳 Complete Chinese'; + +COMMIT; \ No newline at end of file diff --git a/frontend/components/chat/MessageList.tsx b/frontend/components/chat/MessageList.tsx index f60232a..d71bebb 100644 --- a/frontend/components/chat/MessageList.tsx +++ b/frontend/components/chat/MessageList.tsx @@ -1,6 +1,9 @@ import { Sparkles, SquareArrowOutUpRight, ThumbsUp, Copy, RotateCcw } from "lucide-react"; import { Message, DocumentMetadata } from "../../types/chat"; +const DUMMY_COVER_URL = "https://image.aladin.co.kr/product/dummy"; +const DUMMY_BOOK_LINK = "https://www.aladin.co.kr/dummy-link"; + interface Props { messages: Message[]; onOpenCitation?: (meta: DocumentMetadata) => void; @@ -72,7 +75,11 @@ export function MessageList({ messages, onOpenCitation }: Props) { {/* Citation Cards if metadata exists */} {msg.metadata && msg.metadata.length > 0 && Array.from(new Map(msg.metadata.map((m) => [m.id, m])).values()).map((meta) => { - const title = meta.book_info.title; + const title = meta.kr_title || meta.book_info?.title || meta.id; + // Use newly added 'thumbnail' fallback to cover_url + const coverUrl = meta.thumbnail || (meta.book_info?.cover_url !== DUMMY_COVER_URL ? meta.book_info?.cover_url : ""); + const bookLink = meta.link || meta.book_info?.link; + const isClickable = Boolean(onOpenCitation); const interactiveProps = isClickable ? { @@ -91,34 +98,55 @@ export function MessageList({ messages, onOpenCitation }: Props) {
+ {meta.scholar} • {meta.school} +
+- {meta.scholar} - {meta.school} -
-