MuratKomurcu commited on
Commit
d4c2c9b
·
verified ·
1 Parent(s): 3bed7bc

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +304 -38
src/streamlit_app.py CHANGED
@@ -1,40 +1,306 @@
1
- import altair as alt
2
- import numpy as np
3
- import pandas as pd
4
  import streamlit as st
 
 
 
 
 
 
 
 
 
5
 
6
- """
7
- # Welcome to Streamlit!
8
-
9
- Edit `/streamlit_app.py` to customize this app to your heart's desire :heart:.
10
- If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
11
- forums](https://discuss.streamlit.io).
12
-
13
- In the meantime, below is an example of what you can do with just a few lines of code:
14
- """
15
-
16
- num_points = st.slider("Number of points in spiral", 1, 10000, 1100)
17
- num_turns = st.slider("Number of turns in spiral", 1, 300, 31)
18
-
19
- indices = np.linspace(0, 1, num_points)
20
- theta = 2 * np.pi * num_turns * indices
21
- radius = indices
22
-
23
- x = radius * np.cos(theta)
24
- y = radius * np.sin(theta)
25
-
26
- df = pd.DataFrame({
27
- "x": x,
28
- "y": y,
29
- "idx": indices,
30
- "rand": np.random.randn(num_points),
31
- })
32
-
33
- st.altair_chart(alt.Chart(df, height=700, width=700)
34
- .mark_point(filled=True)
35
- .encode(
36
- x=alt.X("x", axis=None),
37
- y=alt.Y("y", axis=None),
38
- color=alt.Color("idx", legend=None, scale=alt.Scale()),
39
- size=alt.Size("rand", legend=None, scale=alt.Scale(range=[1, 150])),
40
- ))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import streamlit as st
2
+ import openai
3
+ from dotenv import load_dotenv
4
+ import os
5
+ from docx import Document
6
+ from fpdf import FPDF
7
+ from io import BytesIO
8
+ import pyrebase
9
+ import requests
10
+ import json
11
 
12
+ load_dotenv()
13
+
14
+ # ✅ Multiple AI Provider Support
15
+ AI_PROVIDERS = {
16
+ "OpenAI": {
17
+ "api_key": os.getenv("OPENAI_API_KEY"),
18
+ "available": bool(os.getenv("OPENAI_API_KEY"))
19
+ },
20
+ "Hugging Face (FREE)": {
21
+ "api_key": os.getenv("HUGGINGFACE_API_KEY"),
22
+ "available": True # Ücretsiz tier var
23
+ },
24
+ "Groq (FREE)": {
25
+ "api_key": os.getenv("GROQ_API_KEY"),
26
+ "available": True # Ücretsiz tier var
27
+ }
28
+ }
29
+
30
+ # OpenAI client (eğer varsa)
31
+ if AI_PROVIDERS["OpenAI"]["available"]:
32
+ openai.api_key = os.getenv("OPENAI_API_KEY")
33
+ client = openai.OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
34
+ else:
35
+ client = None
36
+
37
+ # ✅ Firebase Config
38
+ firebaseConfig = {
39
+ "apiKey": "AIzaSyB9tHRV1jgMKwtwewOhPT555Lh1Lh-31Pc",
40
+ "authDomain": "blogcraftt.firebaseapp.com",
41
+ "projectId": "blogcraftt",
42
+ "storageBucket": "blogcraftt.appspot.com",
43
+ "messagingSenderId": "708843280683",
44
+ "appId": "1:708843280683:web:1ab9d956168b5ad5b89d6e",
45
+ "databaseURL": ""
46
+ }
47
+
48
+ firebase = pyrebase.initialize_app(firebaseConfig)
49
+ auth = firebase.auth()
50
+
51
+ # ✅ Prompt Library Tanımlaması
52
+ prompt_library = {
53
+ "📝 Blog Yazısı": "Sen profesyonel bir Türk blog yazarı ve içerik üreticisisin. Türkçe olarak başlangıç, gelişme ve sonuç yapısıyla en az 1000 kelimelik özgün ve SEO uyumlu bir blog yaz. Başlıklar kullan ve düzenli bir yapıda sun. Yanıtını tamamen Türkçe ver.",
54
+
55
+ "🔗 LinkedIn Post": """Sen LinkedIn'de başarılı bir Türk profesyonel içerik üreticisisin. Türkçe olarak etkili LinkedIn postları yazarsın. Kuralların:
56
+ 1. İlgi çekici bir Türkçe hook ile başla
57
+ 2. Değerli bilgi ver
58
+ 3. Paragraflar kısa olsun (2-3 cümle max)
59
+ 4. Emojiler kullan ama abartma
60
+ 5. Sonunda engaging bir Türkçe soru sor
61
+ 6. İlgili Türkçe hashtagleri ekle
62
+ 7. Profesyonel ama samimi bir Türkçe ton kullan
63
+ 8. 150-200 kelime arasında tut
64
+ Yanıtını tamamen Türkçe ver.""",
65
+
66
+ "🐦 Tweet": "Sen yaratıcı bir Türk içerik üreticisisin. 280 karakteri geçmeyen, kısa, vurucu ve etkileyici bir Türkçe tweet hazırla. Türkçe hashtag kullan ve viral olabilecek şekilde yaz. Yanıtını tamamen Türkçe ver.",
67
+
68
+ "🛍 Ürün Tanıtımı": "Türk pazarlama uzmanı gibi Türkçe ürün tanıtımı yap. Sorun-çözüm odaklı Türkçe yaz. Ürünün faydalarını vurgula ve satış odaklı Türkçe içerik üret. Yanıtını tamamen Türkçe ver.",
69
+
70
+ "📧 Email Marketing": "Profesyonel Türk email pazarlama uzmanısın. Türkçe konu başlığından başlayarak, açılış oranı yüksek, dönüşüm odaklı Türkçe email içeriği yaz. Yanıtını tamamen Türkçe ver.",
71
+
72
+ "🎥 Video Script": "Türk video içerik üreticisisin. Hook, içerik ve call-to-action yapısıyla Türkçe video script'i hazırla. Dakika başına 150 kelime hesabıyla Türkçe yaz. Yanıtını tamamen Türkçe ver."
73
+ }
74
+
75
+ st.set_page_config(page_title="AI Content Factory - Login", layout="wide")
76
+ st.title("🔐 AI Content Factory")
77
+
78
+ # Kullanıcı oturumu
79
+ if 'user' not in st.session_state:
80
+ st.session_state['user'] = None
81
+
82
+ # Email & Şifre Inputları
83
+ st.sidebar.header("User Authentication")
84
+ email = st.sidebar.text_input("📧 Email")
85
+ password = st.sidebar.text_input("🔑 Password", type="password")
86
+
87
+ col1, col2 = st.sidebar.columns(2)
88
+
89
+ with col1:
90
+ if st.sidebar.button("Login"):
91
+ try:
92
+ user = auth.sign_in_with_email_and_password(email, password)
93
+ st.session_state['user'] = user
94
+ st.sidebar.success(f"✅ Welcome {email}")
95
+ except:
96
+ st.sidebar.error("❌ Invalid email or password")
97
+
98
+ with col2:
99
+ if st.sidebar.button("Sign Up"):
100
+ try:
101
+ user = auth.create_user_with_email_and_password(email, password)
102
+ st.sidebar.success("✅ Account created successfully! Please log in.")
103
+ except:
104
+ st.sidebar.error("❌ Failed to register. Email may already be in use or password is weak.")
105
+
106
+ # Oturum varsa logout göster
107
+ if st.session_state['user']:
108
+ if st.sidebar.button("Logout"):
109
+ st.session_state['user'] = None
110
+ st.sidebar.success("✅ Logged out successfully")
111
+
112
+ # Content Generation Section
113
+ if st.session_state['user']:
114
+ st.subheader("✨ Welcome to AI Content Generation")
115
+
116
+ # ✅ Prompt Library Seçici
117
+ st.sidebar.title("📚 Prompt Library")
118
+ selected_prompt_category = st.sidebar.selectbox("Kategori Seç", list(prompt_library.keys()))
119
+ default_prompt = prompt_library[selected_prompt_category]
120
+ custom_prompt = st.sidebar.text_area("✏️ Promptu Düzenle veya Yaz", value=default_prompt, height=150)
121
+
122
+ # ✅ Prompt Kaydetme (Demo)
123
+ if st.sidebar.button("💾 Promptu Kaydet (Demo)"):
124
+ st.sidebar.success("✅ Prompt kaydedildi (demo)")
125
+
126
+ st.sidebar.markdown("---")
127
+
128
+ # Blog Detail Inputs
129
+ st.sidebar.title("Input your Blog Detail")
130
+ st.sidebar.subheader("Enter details of the Blog You want to generate")
131
+
132
+ # Blog title
133
+ blog_title = st.sidebar.text_input("Blog Title")
134
+
135
+ # Keywords input
136
+ keywords = st.sidebar.text_area("Keywords (comma-seperated)")
137
+
138
+ num_words = st.sidebar.slider("Number of words", min_value=250, max_value=1000, step=250)
139
+
140
+ submit_button = st.sidebar.button("Generate")
141
+
142
+ # Ana içerik üretimi
143
+ if submit_button and keywords:
144
+
145
+ # Seçilen promptu al
146
+ final_prompt = custom_prompt.strip()
147
+
148
+ # Öncelik sırası: Groq > Hugging Face (backend'de saklı key'ler)
149
+ current_groq_key = os.getenv("GROQ_API_KEY", "")
150
+ current_hf_key = os.getenv("HUGGINGFACE_API_KEY", "")
151
+
152
+ selected_service = None
153
+ if current_groq_key:
154
+ selected_service = "Groq"
155
+ elif current_hf_key:
156
+ selected_service = "Hugging Face"
157
+ else:
158
+ st.error("⚠️ Sistem yapılandırması eksik. Lütfen yönetici ile iletişime geçin.")
159
+ st.stop()
160
+
161
+ st.info(f"🤖 {selected_service} servisi kullanılıyor...")
162
+
163
+ # API Çağrısı yapacak fonksiyon
164
+ def make_ai_request(prompt, user_message, max_tokens=2048):
165
+ if selected_service == "Groq":
166
+ try:
167
+ url = "https://api.groq.com/openai/v1/chat/completions"
168
+ headers = {
169
+ "Authorization": f"Bearer {current_groq_key}",
170
+ "Content-Type": "application/json"
171
+ }
172
+
173
+ data = {
174
+ "model": "llama3-8b-8192",
175
+ "messages": [
176
+ {"role": "system", "content": prompt},
177
+ {"role": "user", "content": user_message}
178
+ ],
179
+ "max_tokens": min(max_tokens, 2048),
180
+ "temperature": 0.7
181
+ }
182
+
183
+ response = requests.post(url, headers=headers, json=data)
184
+ if response.status_code == 200:
185
+ result = response.json()
186
+ return result['choices'][0]['message']['content']
187
+ else:
188
+ st.warning(f"Groq API hatası, Hugging Face'e geçiliyor...")
189
+ return fallback_to_hf(prompt, user_message)
190
+ except Exception as e:
191
+ st.warning(f"Groq bağlantı hatası, Hugging Face'e geçiliyor...")
192
+ return fallback_to_hf(prompt, user_message)
193
+
194
+ elif selected_service == "Hugging Face":
195
+ return fallback_to_hf(prompt, user_message)
196
+
197
+ return None
198
+
199
+ def fallback_to_hf(prompt, user_message):
200
+ try:
201
+ API_URL = "https://api-inference.huggingface.co/models/meta-llama/Llama-2-7b-chat-hf"
202
+ headers = {"Authorization": f"Bearer {current_hf_key}"}
203
+
204
+ full_prompt = f"{prompt}\n\nUser: {user_message}\nAssistant: Türkçe olarak yanıtlayacağım:"
205
+ payload = {"inputs": full_prompt[:1000], "parameters": {"max_new_tokens": 500}}
206
+
207
+ response = requests.post(API_URL, headers=headers, json=payload)
208
+
209
+ if response.status_code == 200:
210
+ result = response.json()
211
+ if isinstance(result, list) and len(result) > 0:
212
+ generated_text = result[0].get('generated_text', '')
213
+ if "Assistant:" in generated_text:
214
+ return generated_text.split("Assistant:")[-1].strip()
215
+ return generated_text
216
+ return f"HuggingFace ile basit Türkçe içerik: {user_message[:100]}..."
217
+ else:
218
+ return f"📝 Template içerik: {keywords} konusunda {selected_prompt_category} formatında profesyonel Türkçe içerik."
219
+ except Exception as e:
220
+ return f"📝 Template içerik: {keywords} konusunda {selected_prompt_category} formatında profesyonel Türkçe içerik."
221
+
222
+ # Kategoriye göre içerik üretimi
223
+ content_for_download = ""
224
+
225
+ if "Blog" in selected_prompt_category:
226
+ with st.spinner(f"🤖 {selected_service} ile Türkçe blog yazısı oluşturuluyor..."):
227
+ user_message = f"Konu: {keywords}. Yaklaşık {num_words} kelime uzunluğunda, '{blog_title}' başlıklı Türkçe blog yazısı yaz. Yanıtını tamamen Türkçe ver."
228
+ blog_content = make_ai_request(final_prompt, user_message, 4096)
229
+
230
+ if blog_content:
231
+ st.subheader("📝 Oluşturulan Blog Yazısı")
232
+ st.write(blog_content)
233
+ content_for_download = blog_content
234
+ else:
235
+ content_for_download = f"Blog yazısı: {keywords} konusunda içerik oluşturulamadı."
236
+
237
+ elif "LinkedIn" in selected_prompt_category:
238
+ with st.spinner(f"🤖 {selected_service} ile Türkçe LinkedIn postu oluşturuluyor..."):
239
+ user_message = f"Bu konular hakkında profesyonel bir Türkçe LinkedIn postu yaz: {keywords}. Yanıtını tamamen Türkçe ver."
240
+ linkedin_content = make_ai_request(final_prompt, user_message, 600)
241
+
242
+ if linkedin_content:
243
+ st.subheader("📝 Oluşturulan LinkedIn Postu")
244
+ st.write(linkedin_content)
245
+ content_for_download = linkedin_content
246
+ else:
247
+ content_for_download = f"LinkedIn Post: {keywords} hakkında profesyonel bir paylaşım oluşturulamadı."
248
+
249
+ elif "Tweet" in selected_prompt_category:
250
+ with st.spinner(f"🤖 {selected_service} ile Türkçe tweet oluşturuluyor..."):
251
+ user_message = f"Bu konular hakkında Türkçe tweet yaz: {keywords}. Yanıtını tamamen Türkçe ver."
252
+ tweet_content = make_ai_request(final_prompt, user_message, 100)
253
+
254
+ if tweet_content:
255
+ st.subheader("📝 Oluşturulan Tweet")
256
+ st.write(tweet_content)
257
+ content_for_download = tweet_content
258
+ else:
259
+ content_for_download = f"Tweet: {keywords} hakkında kısa bir paylaşım oluşturulamadı."
260
+
261
+ else:
262
+ with st.spinner(f"🤖 {selected_service} ile Türkçe {selected_prompt_category} oluşturuluyor..."):
263
+ user_message = f"Bu konular hakkında Türkçe içerik yaz: {keywords}. Yanıtını tamamen Türkçe ver."
264
+ general_content = make_ai_request(final_prompt, user_message, 2048)
265
+
266
+ if general_content:
267
+ st.subheader(f"📝 Oluşturulan {selected_prompt_category}")
268
+ st.write(general_content)
269
+ content_for_download = general_content
270
+ else:
271
+ content_for_download = f"{selected_prompt_category}: {keywords} konusunda içerik oluşturulamadı."
272
+
273
+ # DOCX İndirme
274
+ full_content = f"""
275
+ {selected_prompt_category} İçeriği
276
+ Başlık: {blog_title}
277
+ Anahtar Kelimeler: {keywords}
278
+ Kullanılan AI Servisi: {selected_service}
279
+ Kullanılan Prompt: {final_prompt}
280
+
281
+ --- İÇERİK ---
282
+ {content_for_download}
283
+ """
284
+
285
+ def generate_docx(content):
286
+ buffer = BytesIO()
287
+ doc = Document()
288
+ doc.add_paragraph(content)
289
+ doc.save(buffer)
290
+ buffer.seek(0)
291
+ return buffer
292
+
293
+ docx_file = generate_docx(full_content)
294
+
295
+ st.download_button(
296
+ label="📄 Download as DOCX",
297
+ data=docx_file,
298
+ file_name=f"{selected_prompt_category.replace('🔗', '').replace('📝', '').replace('🐦', '').replace('🛍', '').strip()}_output.docx",
299
+ mime="application/vnd.openxmlformats-officedocument.wordprocessingml.document"
300
+ )
301
+
302
+ elif submit_button and not keywords:
303
+ st.warning("⚠️ Lütfen keywords girin!")
304
+
305
+ else:
306
+ st.warning("⚠️ Lütfen giriş yapın veya kayıt olun.")