Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -14,20 +14,27 @@ BRAVE_ENDPOINT = "https://api.search.brave.com/res/v1/web/search"
|
|
| 14 |
IMAGE_API_URL = "http://211.233.58.201:7896"
|
| 15 |
MAX_TOKENS = 7_999
|
| 16 |
|
| 17 |
-
# λΈλ‘κ·Έ ν
νλ¦Ώ λ° μ€νμΌ μ μ
|
| 18 |
BLOG_TEMPLATES = {
|
| 19 |
-
"standard": "
|
| 20 |
-
"tutorial": "λ¨κ³λ³ νν 리μΌ
|
| 21 |
-
"review": "μ ν/μλΉμ€
|
| 22 |
-
"storytelling": "
|
| 23 |
-
"seo_optimized": "
|
| 24 |
}
|
| 25 |
|
| 26 |
BLOG_TONES = {
|
| 27 |
-
"professional": "μ λ¬Έμ μ΄κ³ 곡μμ μΈ
|
| 28 |
-
"casual": "μΉκ·Όνκ³ λν체
|
| 29 |
-
"humorous": "
|
| 30 |
-
"storytelling": "
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
}
|
| 32 |
|
| 33 |
# ββββββββββββββββββββββββββββββββ λ‘κΉ
ββββββββββββββββββββββββββββββββββββββ
|
|
@@ -155,7 +162,7 @@ def get_system_prompt(template="standard", tone="professional", word_count=1750)
|
|
| 155 |
return final_prompt
|
| 156 |
|
| 157 |
# ββββββββββββββββββββββββββββββββ Brave Search API βββββββββββββββββββββββββ
|
| 158 |
-
def brave_search(query: str, count: int =
|
| 159 |
"""
|
| 160 |
Brave Web Search API νΈμΆ β list[dict]
|
| 161 |
λ°ν νλ: index, title, link, snippet, displayed_link
|
|
@@ -168,7 +175,7 @@ def brave_search(query: str, count: int = 5):
|
|
| 168 |
"Accept-Encoding": "gzip",
|
| 169 |
"X-Subscription-Token": BRAVE_KEY
|
| 170 |
}
|
| 171 |
-
params = {"q": query, "count": str(count)}
|
| 172 |
|
| 173 |
for attempt in range(3): # μ΅λ 3λ² μ¬μλ
|
| 174 |
try:
|
|
@@ -185,7 +192,7 @@ def brave_search(query: str, count: int = 5):
|
|
| 185 |
raise ValueError("κ²μ κ²°κ³Όκ° μμ΅λλ€")
|
| 186 |
|
| 187 |
arts = []
|
| 188 |
-
for i, res in enumerate(raw[:count], 1):
|
| 189 |
url = res.get("url", res.get("link", ""))
|
| 190 |
host = re.sub(r"https?://(www\.)?", "", url).split("/")[0]
|
| 191 |
arts.append({
|
|
@@ -221,7 +228,7 @@ def mock_results(query: str) -> str:
|
|
| 221 |
def do_web_search(query: str) -> str:
|
| 222 |
"""μΉ κ²μ μν λ° κ²°κ³Ό ν¬λ§·ν
"""
|
| 223 |
try:
|
| 224 |
-
arts = brave_search(query,
|
| 225 |
if not arts:
|
| 226 |
logging.warning("κ²μ κ²°κ³Ό μμ, λ체 μ½ν
μΈ μ¬μ©")
|
| 227 |
return mock_results(query)
|
|
@@ -271,7 +278,7 @@ def keywords(text: str, top=5):
|
|
| 271 |
|
| 272 |
# ββββββββββββββββββββββββββββββββ Streamlit UI ββββββββββββββββββββββββββββ
|
| 273 |
def ginigen_app():
|
| 274 |
-
st.title("
|
| 275 |
|
| 276 |
# μΈμ
κΈ°λ³Έκ°
|
| 277 |
defaults = dict(
|
|
@@ -294,17 +301,31 @@ def ginigen_app():
|
|
| 294 |
# λΈλ‘κ·Έ ν
νλ¦Ώ λ° μ€νμΌ μ ν
|
| 295 |
sb.subheader("λΈλ‘κ·Έ μ€νμΌ μ€μ ")
|
| 296 |
sb.selectbox("λΈλ‘κ·Έ ν
νλ¦Ώ", options=list(BLOG_TEMPLATES.keys()),
|
| 297 |
-
format_func=lambda x: x
|
| 298 |
key="blog_template")
|
| 299 |
|
| 300 |
sb.selectbox("λΈλ‘κ·Έ ν€", options=list(BLOG_TONES.keys()),
|
| 301 |
-
format_func=lambda x: x
|
| 302 |
key="blog_tone")
|
| 303 |
|
| 304 |
sb.slider("λΈλ‘κ·Έ κΈΈμ΄ (λ¨μ΄ μ)", 800, 3000, 1750, key="word_count")
|
| 305 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 306 |
sb.subheader("κΈ°ν μ€μ ")
|
| 307 |
-
sb.toggle("μλ μ μ₯",
|
| 308 |
sb.toggle("μ΄λ―Έμ§ μλ μμ±", key="generate_image")
|
| 309 |
|
| 310 |
# μΉ κ²μ ν κΈ (λͺ¨λν°λ§μ μν΄ μ μ§νλ κΈ°λ³Έκ°μ False)
|
|
@@ -322,7 +343,7 @@ def ginigen_app():
|
|
| 322 |
title = title.group(1).strip() if title else "blog"
|
| 323 |
sb.subheader("μ΅κ·Ό λΈλ‘κ·Έ λ€μ΄λ‘λ")
|
| 324 |
c1, c2 = sb.columns(2)
|
| 325 |
-
c1.download_button("
|
| 326 |
file_name=f"{title}.md", mime="text/markdown")
|
| 327 |
c2.download_button("HTML", md_to_html(latest_blog, title),
|
| 328 |
file_name=f"{title}.html", mime="text/html")
|
|
@@ -350,8 +371,16 @@ def ginigen_app():
|
|
| 350 |
if "image" in m:
|
| 351 |
st.image(m["image"], caption=m.get("image_caption", ""))
|
| 352 |
|
| 353 |
-
# ββ μ¬μ©μ μ
λ ₯
|
| 354 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 355 |
st.session_state.messages.append({"role": "user", "content": prompt})
|
| 356 |
with st.chat_message("user"): st.markdown(prompt)
|
| 357 |
|
|
@@ -400,7 +429,7 @@ def ginigen_app():
|
|
| 400 |
# λ³Έλ¬Έ λ€μ΄λ‘λ λ²νΌ (MD / HTML)
|
| 401 |
st.subheader("μ΄ λΈλ‘κ·Έ λ€μ΄λ‘λ")
|
| 402 |
b1, b2 = st.columns(2)
|
| 403 |
-
b1.download_button("
|
| 404 |
file_name=f"{prompt[:30]}.md", mime="text/markdown")
|
| 405 |
b2.download_button("HTML", md_to_html(answer, prompt[:30]),
|
| 406 |
file_name=f"{prompt[:30]}.html", mime="text/html")
|
|
|
|
| 14 |
IMAGE_API_URL = "http://211.233.58.201:7896"
|
| 15 |
MAX_TOKENS = 7_999
|
| 16 |
|
| 17 |
+
# λΈλ‘κ·Έ ν
νλ¦Ώ λ° μ€νμΌ μ μ (νκΈν)
|
| 18 |
BLOG_TEMPLATES = {
|
| 19 |
+
"standard": "νμ€ 8λ¨κ³ νλ μμν¬ λΈλ‘κ·Έ",
|
| 20 |
+
"tutorial": "λ¨κ³λ³ νν λ¦¬μΌ νμ",
|
| 21 |
+
"review": "μ ν/μλΉμ€ 리뷰 νμ",
|
| 22 |
+
"storytelling": "μ€ν 리ν
λ§ νμ",
|
| 23 |
+
"seo_optimized": "SEO μ΅μ ν λΈλ‘κ·Έ"
|
| 24 |
}
|
| 25 |
|
| 26 |
BLOG_TONES = {
|
| 27 |
+
"professional": "μ λ¬Έμ μ΄κ³ 곡μμ μΈ ν€",
|
| 28 |
+
"casual": "μΉκ·Όνκ³ λν체 μ€μ¬ ν€",
|
| 29 |
+
"humorous": "μ λ¨Έλ¬μ€ν μ κ·Ό",
|
| 30 |
+
"storytelling": "μ΄μΌκΈ° μ€μ¬μ μ κ·Ό"
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
# μμ λΈλ‘κ·Έ μ£Όμ
|
| 34 |
+
EXAMPLE_TOPICS = {
|
| 35 |
+
"example1": "2025λ
λ°λ λΆλμ° μΈκΈ μ λ: μΌλ° κ°μ μ λ―ΈμΉλ μν₯κ³Ό μ μΈ μ λ΅",
|
| 36 |
+
"example2": "2025λ
μ¬λ¦ μ κ΅ μ§μλ³ λν μΆμ μ΄μ 리μ μ¨μ λͺ
μ μΆμ²",
|
| 37 |
+
"example3": "2025λ
μ£Όλͺ©ν΄μΌ ν μ μ±μ₯ μ°μ
ν¬μ κ°μ΄λ: μΈκ³΅μ§λ₯ κ΄λ ¨ λ°κ΅΄ μ λ΅"
|
| 38 |
}
|
| 39 |
|
| 40 |
# ββββββββββββββββββββββββββββββββ λ‘κΉ
ββββββββββββββββββββββββββββββββββββββ
|
|
|
|
| 162 |
return final_prompt
|
| 163 |
|
| 164 |
# ββββββββββββββββββββββββββββββββ Brave Search API βββββββββββββββββββββββββ
|
| 165 |
+
def brave_search(query: str, count: int = 20): # κΈ°λ³Έκ°μ 20μΌλ‘ λ³κ²½
|
| 166 |
"""
|
| 167 |
Brave Web Search API νΈμΆ β list[dict]
|
| 168 |
λ°ν νλ: index, title, link, snippet, displayed_link
|
|
|
|
| 175 |
"Accept-Encoding": "gzip",
|
| 176 |
"X-Subscription-Token": BRAVE_KEY
|
| 177 |
}
|
| 178 |
+
params = {"q": query, "count": str(count)} # μΉ΄μ΄νΈ νλΌλ―Έν° μ λ¬
|
| 179 |
|
| 180 |
for attempt in range(3): # μ΅λ 3λ² μ¬μλ
|
| 181 |
try:
|
|
|
|
| 192 |
raise ValueError("κ²μ κ²°κ³Όκ° μμ΅λλ€")
|
| 193 |
|
| 194 |
arts = []
|
| 195 |
+
for i, res in enumerate(raw[:count], 1): # countλ§νΌ λ°λ³΅
|
| 196 |
url = res.get("url", res.get("link", ""))
|
| 197 |
host = re.sub(r"https?://(www\.)?", "", url).split("/")[0]
|
| 198 |
arts.append({
|
|
|
|
| 228 |
def do_web_search(query: str) -> str:
|
| 229 |
"""μΉ κ²μ μν λ° κ²°κ³Ό ν¬λ§·ν
"""
|
| 230 |
try:
|
| 231 |
+
arts = brave_search(query, 20) # μ¬κΈ°λ 20μΌλ‘ λ³κ²½
|
| 232 |
if not arts:
|
| 233 |
logging.warning("κ²μ κ²°κ³Ό μμ, λ체 μ½ν
μΈ μ¬μ©")
|
| 234 |
return mock_results(query)
|
|
|
|
| 278 |
|
| 279 |
# ββββββββββββββββββββββββββββββββ Streamlit UI ββββββββββββββββββββββββββββ
|
| 280 |
def ginigen_app():
|
| 281 |
+
st.title("μ§λμ λΈλ‘κ·Έ")
|
| 282 |
|
| 283 |
# μΈμ
κΈ°λ³Έκ°
|
| 284 |
defaults = dict(
|
|
|
|
| 301 |
# λΈλ‘κ·Έ ν
νλ¦Ώ λ° μ€νμΌ μ ν
|
| 302 |
sb.subheader("λΈλ‘κ·Έ μ€νμΌ μ€μ ")
|
| 303 |
sb.selectbox("λΈλ‘κ·Έ ν
νλ¦Ώ", options=list(BLOG_TEMPLATES.keys()),
|
| 304 |
+
format_func=lambda x: BLOG_TEMPLATES[x],
|
| 305 |
key="blog_template")
|
| 306 |
|
| 307 |
sb.selectbox("λΈλ‘κ·Έ ν€", options=list(BLOG_TONES.keys()),
|
| 308 |
+
format_func=lambda x: BLOG_TONES[x],
|
| 309 |
key="blog_tone")
|
| 310 |
|
| 311 |
sb.slider("λΈλ‘κ·Έ κΈΈμ΄ (λ¨μ΄ μ)", 800, 3000, 1750, key="word_count")
|
| 312 |
|
| 313 |
+
# μμ μ£Όμ μ ν
|
| 314 |
+
sb.subheader("μμ μ£Όμ ")
|
| 315 |
+
if sb.button("μλ°μ€ν¬λ¦½νΈ νλ μμν¬ λΉκ΅", key="example1"):
|
| 316 |
+
st.session_state.example_topic = EXAMPLE_TOPICS["example1"]
|
| 317 |
+
st.experimental_rerun()
|
| 318 |
+
|
| 319 |
+
if sb.button("μ΄λ³΄μλ₯Ό μν μ£Όμ ν¬μ κ°μ΄λ", key="example2"):
|
| 320 |
+
st.session_state.example_topic = EXAMPLE_TOPICS["example2"]
|
| 321 |
+
st.experimental_rerun()
|
| 322 |
+
|
| 323 |
+
if sb.button("ν¨κ³Όμ μΈ μκ° κ΄λ¦¬ μ λ΅", key="example3"):
|
| 324 |
+
st.session_state.example_topic = EXAMPLE_TOPICS["example3"]
|
| 325 |
+
st.experimental_rerun()
|
| 326 |
+
|
| 327 |
sb.subheader("κΈ°ν μ€μ ")
|
| 328 |
+
sb.toggle("μλ μ μ₯", key="auto_save")
|
| 329 |
sb.toggle("μ΄λ―Έμ§ μλ μμ±", key="generate_image")
|
| 330 |
|
| 331 |
# μΉ κ²μ ν κΈ (λͺ¨λν°λ§μ μν΄ μ μ§νλ κΈ°λ³Έκ°μ False)
|
|
|
|
| 343 |
title = title.group(1).strip() if title else "blog"
|
| 344 |
sb.subheader("μ΅κ·Ό λΈλ‘κ·Έ λ€μ΄λ‘λ")
|
| 345 |
c1, c2 = sb.columns(2)
|
| 346 |
+
c1.download_button("λ§ν¬λ€μ΄", latest_blog,
|
| 347 |
file_name=f"{title}.md", mime="text/markdown")
|
| 348 |
c2.download_button("HTML", md_to_html(latest_blog, title),
|
| 349 |
file_name=f"{title}.html", mime="text/html")
|
|
|
|
| 371 |
if "image" in m:
|
| 372 |
st.image(m["image"], caption=m.get("image_caption", ""))
|
| 373 |
|
| 374 |
+
# ββ μ¬μ©μ μ
λ ₯ λλ μμ μ£Όμ μ²λ¦¬
|
| 375 |
+
prompt = st.chat_input("무μμ λμλ릴κΉμ?")
|
| 376 |
+
|
| 377 |
+
# μμ μ£Όμ κ° μ νλμμΌλ©΄ μ²λ¦¬
|
| 378 |
+
if hasattr(st.session_state, 'example_topic') and st.session_state.example_topic:
|
| 379 |
+
prompt = st.session_state.example_topic
|
| 380 |
+
# μ²λ¦¬ ν μμ μ£Όμ μ΄κΈ°ν
|
| 381 |
+
del st.session_state.example_topic
|
| 382 |
+
|
| 383 |
+
if prompt:
|
| 384 |
st.session_state.messages.append({"role": "user", "content": prompt})
|
| 385 |
with st.chat_message("user"): st.markdown(prompt)
|
| 386 |
|
|
|
|
| 429 |
# λ³Έλ¬Έ λ€μ΄λ‘λ λ²νΌ (MD / HTML)
|
| 430 |
st.subheader("μ΄ λΈλ‘κ·Έ λ€μ΄λ‘λ")
|
| 431 |
b1, b2 = st.columns(2)
|
| 432 |
+
b1.download_button("λ§ν¬λ€μ΄", answer,
|
| 433 |
file_name=f"{prompt[:30]}.md", mime="text/markdown")
|
| 434 |
b2.download_button("HTML", md_to_html(answer, prompt[:30]),
|
| 435 |
file_name=f"{prompt[:30]}.html", mime="text/html")
|