From 3b9a4fcd769c9e659a0184085df0c3d346dd8faa Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 29 Jul 2026 08:37:29 +0000 Subject: [PATCH] Add root .env template for GEMINI_API_KEY Provide .env.example, ignore local .env, and teach generate_draft.py to load the repo-root .env so PoC #1 can use Gemini without exporting keys in the shell every time. Co-authored-by: okuma --- .env.example | 3 +++ .gitignore | 5 +++++ poc/tone-corpus/README.md | 5 +++-- poc/tone-corpus/generate_draft.py | 25 +++++++++++++++++++++++++ 4 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 .env.example diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..070cc05 --- /dev/null +++ b/.env.example @@ -0,0 +1,3 @@ +# Copy to .env and fill in values. Never commit .env. +# Get a key from Google AI Studio: https://aistudio.google.com/apikey +GEMINI_API_KEY= diff --git a/.gitignore b/.gitignore index 57ee51f..07ca94e 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,8 @@ poc/tone-corpus/data/ *.jsonl *.zip + +# Local secrets (API keys). Commit .env.example only. +.env +.env.* +!.env.example diff --git a/poc/tone-corpus/README.md b/poc/tone-corpus/README.md index 01de4b8..40e8cf9 100644 --- a/poc/tone-corpus/README.md +++ b/poc/tone-corpus/README.md @@ -48,8 +48,9 @@ Gemini(`google-genai`)를 쓴다 — 기본 모델은 `--model`로 바꿀 수 ### `GEMINI_API_KEY`는 어디에 설정하나 -- **본인 로컬 환경에서 이 스크립트를 실제로 돌릴 거라면**: 그쪽 터미널에서 - `export GEMINI_API_KEY=...`(임시) 또는 셸 프로필/`.env` 파일(영구)에 등록. Google AI Studio에서 +- **권장**: 저장소 루트 `.env`에 `GEMINI_API_KEY=...`를 넣는다 (템플릿은 `.env.example`). + `generate_draft.py`가 실행 시 이 파일을 읽는다. `.env`는 `.gitignore`로 커밋되지 않는다. +- **대안**: 터미널에서 `export GEMINI_API_KEY=...`(임시) 또는 셸 프로필에 등록. Google AI Studio에서 발급한 키를 그대로 쓰면 된다. - **이 Claude Code 세션/환경에서 직접 실행해보고 싶다면**: 이 대화창에 `export GEMINI_API_KEY=실제키`를 실행해달라고 하면 되는데, 그러면 **키 값이 이 대화 기록에 그대로 남는다** — 무제한 결제 키가 아니라 diff --git a/poc/tone-corpus/generate_draft.py b/poc/tone-corpus/generate_draft.py index 68d2844..a3d0b24 100644 --- a/poc/tone-corpus/generate_draft.py +++ b/poc/tone-corpus/generate_draft.py @@ -10,6 +10,7 @@ that voice. This is the server-fallback path described in prompt contract (exemplars + context in, one draft out) stays the same. Usage: + # Prefer repo-root .env (GEMINI_API_KEY=...), or: export GEMINI_API_KEY=... python3 generate_draft.py --style style_examples.txt --context context.txt @@ -20,6 +21,28 @@ with the incoming message that needs a reply. import argparse import os import sys +from pathlib import Path + + +def load_dotenv_if_present(): + """Load KEY=VALUE pairs from the nearest .env (repo root preferred).""" + if os.environ.get("GEMINI_API_KEY"): + return + here = Path(__file__).resolve() + candidates = [here.parent / ".env", here.parent.parent.parent / ".env", Path.cwd() / ".env"] + for env_path in candidates: + if not env_path.is_file(): + continue + for raw in env_path.read_text(encoding="utf-8").splitlines(): + line = raw.strip() + if not line or line.startswith("#") or "=" not in line: + continue + key, _, value = line.partition("=") + key, value = key.strip(), value.strip().strip("'").strip('"') + if key and key not in os.environ: + os.environ[key] = value + break + SYSTEM_PROMPT = """너는 어떤 사람의 '분신'이다. 아래 예시 발화들의 말투(어휘, 문장 길이, 이모티콘 습관, 격식 정도)를 \ 그대로 따라서, 대화의 마지막 메시지에 대한 답장 '초안 하나만' 자연스러운 한국어로 작성해라. @@ -44,6 +67,8 @@ def main(): ap.add_argument("--model", default="gemini-2.5-flash") args = ap.parse_args() + load_dotenv_if_present() + with open(args.style, encoding="utf-8") as f: style_examples = [l.strip() for l in f if l.strip()] with open(args.context, encoding="utf-8") as f: