article_writer / src /streamlit_app.py
GolabiSib's picture
Update src/streamlit_app.py
76867f7 verified
import os
import streamlit as st
from openai import OpenAI
from dotenv import load_dotenv
from reportlab.pdfgen import canvas
import base64
from token_optimizer import optimize_prompt
# ------------------------
# 🔑 تنظیم کلاینت OpenAI-compatible (Hugging Face)
# ------------------------
load_dotenv()
client = OpenAI(
base_url=os.getenv("OPENROUTER_BASE_URL"),
api_key=os.getenv("OPENROUTER_API_KEY")
)
# ------------------------
# 🎨 استایل اختیاری
# ------------------------
with open("src/theme.css") as f:
st.markdown(f"<style>{f.read()}</style>", unsafe_allow_html=True)
# ------------------------
# Page setup
# ------------------------
st.set_page_config(page_title="AI Article Writer", page_icon="🧠", layout="centered")
st.title("🧠 AI Article Writer")
st.subheader("تولید مقاله حرفه‌ای با هوش مصنوعی")
st.divider()
# ------------------------
# Inputs
# ------------------------
topic = st.text_input("موضوع مقاله:",key="topic_input", placeholder="مثلاً تاثیر هوش مصنوعی بر آموزش...")
tone = st.selectbox("لحن مقاله:", ["علمی", "غیررسمی", "تخصصی", "داستانی", "تحلیلی", "احساسی", "طنزآمیز ", "ژورنالیستی"], key="tone_select")
language = st.selectbox("زبان مقاله:", ["فارسی", "انگلیسی"], key="lang_select")
length = st.select_slider("طول مقاله(پاراگراف):", options=list(range(1,11)), value=3, key="length_slider") # 1 to 10 scale
keywords = st.text_input("کلمات کلیدی (اختیاری):",key="keywords_input", placeholder="مثلاً آموزش، فناوری، هوش مصنوعی...")
references_num = st.number_input("تعداد منابع مورد استفاده (اختیاری):", 0, 5, 1, key="ref_num")
references_condition = st.text_input("شرایط منابع (اختیاری):",key="ref_cond", placeholder="مثلاً منابع معتبر و به‌روز...")
st.divider()
# ------------------------
# Model selection
# ------------------------
model_options = {
"🦾 مدل بزرگ، مناسب تولید محتوای باکیفیت و خلاقانه (Meta-Llama Maverick)":
"meta-llama/llama-4-maverick:free",
"✍️ مدل 24B، مناسب مقاله‌نویسی و متن‌های طولانی با انسجام بالا (Mistral-Small 3.2)":
"mistralai/mistral-small-3.2-24b-instruct:free",
"🚀 مدل خیلی بزرگ، مناسب کارهای سنگین، تحلیل عمیق و تولید محتوای حرفه‌ای (Hermes 405B)":
"nousresearch/hermes-3-llama-3.1-405b:free",
"⚡ سریع و سبک، مناسب متن‌نویسی روزمره و پاسخ‌های کوتاه (DeepHermes 8B)":
"nousresearch/deephermes-3-llama-3-8b-preview:free",
# "nvidia/nemotron-nano-12b-v2-vl:free":"nvidia/nemotron-nano-12b-v2-vl:free",
# "minimax/minimax-m2:free":"minimax/minimax-m2:free",
}
selected_label = st.selectbox("مدل مورد استفاده:", list(model_options.keys()), key="model_label_select")
model_name = model_options[selected_label]
# ------------------------
# Advanced settings
# ------------------------
with st.expander("⚙️ تنظیمات پیشرفته (برای کاربران حرفه‌ای)", expanded=False):
st.caption("در صورت نیاز می‌توانید تنظیمات مدل را تغییر دهید:")
temperature = st.slider("میزان خلاقیت مدل (Temperature)", 0.1, 1.0, 0.3)
max_tokens = st.slider("حداکثر تعداد توکن خروجی", 200, 2000, 800)
st.divider()
# ------------------------
# Generate button
# ------------------------
if st.button("✍️ تولید مقاله"):
if not topic.strip():
st.warning("لطفاً موضوع مقاله را وارد کنید 🌱")
else:
with st.spinner("در حال تولید مقاله..."):
prompt = f"""
You are an expert human writer and researcher.
With'{references_condition}' on your mind, and using '{references_num}' credible sources if needed,
Write a high-quality, well-researched article in '{language}' with a '{tone}' tone about the topic: '{topic}'.
Requirements:
- Follow SEO principles and naturally include these keywords if relevant: '{keywords}'
- Structure:
1️⃣ A compelling title
2️⃣ An engaging introduction with a hook
3️⃣ Multiple well-organized paragraphs with clear subheaders
4️⃣ Examples, recent insights, or credible statistics when useful
5️⃣ A strong conclusion with a key takeaway
- Style:
- Human-like, smooth, and conversational writing (not robotic)
- No hallucinated facts — ensure clarity and accuracy
- Avoid repetition and filler content
- Maintain logical flow and readability
Length:
- Write a '{length}' paragraph article.
References:
- If '{references_num}' > 0, include '{references_num}' credible sources or references at the end.
Make the content professional, coherent, informative, and enjoyable to read.
"""
# بهینه‌سازی پرامپت قبل از ارسال به مدل
prompt = optimize_prompt(prompt)
try:
response = client.chat.completions.create(
model=model_name,
messages=[
{"role": "system", "content": "You are a professional article writer."},
{"role": "user", "content": prompt}
],
temperature=temperature,
max_tokens=max_tokens
)
article_text = response.choices[0].message.content
st.success("✅ مقاله تولید شد:")
st.text_area("📄 متن مقاله:", value=article_text, height=400)
# ✅ دکمه دانلود TXT
b64 = base64.b64encode(article_text.encode()).decode()
href = f'<a href="data:file/txt;base64,{b64}" download="article.txt">📥 دانلود نسخه متنی</a>'
st.markdown(href, unsafe_allow_html=True)
# ✅ دکمه دانلود PDF
# ✅ ذخیره مقاله تولیدشده در حافظه موقت Session
if "articles_session" not in st.session_state:
st.session_state.articles_session = []
st.session_state.articles_session.append({
"topic": st.session_state.get("topic_input", topic),
"tone": st.session_state.get("tone_select", tone),
"language": st.session_state.get("lang_select", language),
"length": st.session_state.get("length_slider", length),
"keywords": st.session_state.get("keywords_input", keywords),
"references_num": st.session_state.get("ref_num", references_num),
"references_condition": st.session_state.get("ref_cond", references_condition),
"model_label": st.session_state.get("model_label_select", selected_label),
"content": article_text,
})
st.info(f"📌 مقاله ذخیره شد — تعداد {len(st.session_state.articles_session)} مورد")
except Exception as e:
st.error(f"⚠️ خطا در فراخوانی مدل: {e}")
# 🗂️ نمایش نتایج قبلی (موقت)
if st.session_state.get("articles_session"):
st.subheader("🗂️ نتایج قبلی (تا زمان بسته شدن صفحه)")
for i, item in enumerate(st.session_state.articles_session):
with st.expander(f"📄 مقاله {i+1}: {item['topic']}"):
st.markdown(f"**موضوع:** {item['topic']}")
st.markdown(f"**لحن:** {item['tone']}")
st.markdown(f"**زبان:** {item['language']}")
st.markdown(f"**طول مقاله:** {item['length']} پاراگراف")
st.markdown(f"**کلمات کلیدی:** {item['keywords']}")
st.markdown(f"**تعداد منابع:** {item['references_num']}")
st.markdown(f"**شرایط منابع:** {item['references_condition']}")
st.markdown(f"**مدل استفاده شده:** {item['model_label']}")
st.markdown("---")
st.write(item["content"])
# 🧭 اجرا:
# streamlit run src/article_writer.py