Spaces:
Running
Running
File size: 3,337 Bytes
21bdc64 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | # Claude Haiku๋ก ํด๋ฌ์คํฐ์ ์๋ยทํ
๋ง๋ช
์ ๋ถ๋ฅํ๊ณ ๋ง์ผํ
์ ์๊น์ง ํ ๋ฒ์ ์์ฑํ๋ ๋ชจ๋
import os
import json
import anthropic
MODEL = "claude-haiku-4-5"
USD_TO_KRW = 1400 # ๋น์ฉ ํ์ฐ์ฉ ๋๋ต๊ฐ
INTENT_LABELS = {
"info": "์ ๋ณด ํ์ํ",
"transactional": "๊ตฌ๋งค/๊ฑฐ๋ํ",
"navigational": "๋ธ๋๋/๋ด๋น๊ฒ์ด์
ํ",
"mixed": "ํผํฉํ",
}
SYSTEM = """๋๋ ๊ฒ์ ํค์๋ ํด๋ฌ์คํฐ๋ฅผ ๋ถ์ํ๋ ๋ง์ผํ
๋ถ์๊ฐ๋ค. ๊ฐ ํด๋ฌ์คํฐ์ ๋ํด ๋ ๊ฐ์ง๋ฅผ ํ๋จํ๋ค.
1. intent โ ๊ฒ์ ์๋๋ฅผ ์ ํํ ํ๋๋ก ๋ถ๋ฅ
- info: ๋ฐฉ๋ฒยท์ถ์ฒยท๋น๊ตยทํ๊ธฐยท๊ฐ์ด๋ ๋ฑ ์ ๋ณด ํ์
- transactional: ๊ตฌ๋งคยท๊ฐ๊ฒฉยท์ต์ ๊ฐยท์ฃผ๋ฌธ ๋ฑ ๊ฑฐ๋
- navigational: ํน์ ๋ธ๋๋ยท์ฌ์ดํธ๋ก ์ด๋
- mixed: ์๊ฐ ์์ฌ ํ๋๋ก ๋จ์ ํ๊ธฐ ์ด๋ ค์
2. theme โ ํด๋ฌ์คํฐ๋ฅผ ๋ํํ๋ 2~6์ด์ ์ ์์ฐ์ค๋ฌ์ด ํ๊ตญ์ด ํ
๋ง ๊ทธ๋ฃน๋ช
(์: "์บ ํ ๊ฐ๊ตฌ", "์ด๋ณด ์
๋ฌธ ๊ฐ์ด๋", "๋๊ณ ๋๋ฐฉ")
๊ทธ๋ฆฌ๊ณ ์ ์ฒด ํด๋ฌ์คํฐ ํจํด์ ๋ณด๊ณ ์ค์๊ธฐ์
(SMB)์ด ๋ฐ๋ก ์คํํ ์ ์๋ ๋ง์ผํ
์ก์
์ ์ 1๊ฐ๋ฅผ 2~3๋ฌธ์ฅ์ผ๋ก ๊ตฌ์ฒด์ ์ผ๋ก ์์ฑํ๋ค.
๋ฐ๋์ JSON๋ง ์ถ๋ ฅํ๋ค. ํ์:
{"clusters":[{"cluster_id":0,"intent":"transactional","theme":"์บ ํ ๊ฐ๊ตฌ"}],"marketing_suggestion":"..."}"""
def _client() -> anthropic.Anthropic:
return anthropic.Anthropic() # ANTHROPIC_API_KEY๋ ํ๊ฒฝ๋ณ์์์ ๋ก๋
def classify_clusters(clusters: list[dict]) -> dict:
# ํด๋ฌ์คํฐ์ intent/intent_label/theme๋ฅผ ์ฑ์ฐ๊ณ , ๋๋ ๋น์คยท๋ง์ผํ
์ ์ยทํ ํฐ ์ฌ์ฉ๋์ ๋ฐํ
if not clusters:
return {"intent_breakdown": {}, "marketing_suggestion": None, "usage": None}
listing = "\n".join(
f"{c['cluster_id']}: {c['cluster_label']} โ {', '.join(c['top_keywords'])}"
for c in clusters
)
res = _client().messages.create(
model=MODEL,
max_tokens=1500,
system=SYSTEM,
messages=[{"role": "user", "content": f"๋ค์ ํด๋ฌ์คํฐ๋ฅผ ๋ถ์ํด๋ผ.\n{listing}"}],
)
text = next(b.text for b in res.content if b.type == "text").strip()
if text.startswith("```"):
text = text.split("```")[1].lstrip("json").strip()
parsed = json.loads(text)
by_id = {item["cluster_id"]: item for item in parsed.get("clusters", [])}
for c in clusters:
item = by_id.get(c["cluster_id"], {})
intent = item.get("intent", "mixed")
if intent not in INTENT_LABELS:
intent = "mixed"
c["intent"] = intent
c["intent_label"] = INTENT_LABELS[intent]
c["theme"] = item.get("theme") or c["cluster_label"] # ํ
๋ง๋ช
, ์์ผ๋ฉด ๋ํ ํค์๋
breakdown: dict[str, int] = {}
for c in clusters:
breakdown[c["intent"]] = breakdown.get(c["intent"], 0) + c["total_search_volume"]
usd = res.usage.input_tokens / 1e6 * 1 + res.usage.output_tokens / 1e6 * 5
return {
"intent_breakdown": breakdown,
"marketing_suggestion": parsed.get("marketing_suggestion"),
"usage": {
"input_tokens": res.usage.input_tokens,
"output_tokens": res.usage.output_tokens,
"cost_usd": round(usd, 5),
"cost_krw": round(usd * USD_TO_KRW, 1),
},
}
|