coingimp commited on
Commit
922fd01
·
verified ·
1 Parent(s): dbffe50

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +173 -0
app.py ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import numpy as np
3
+ from sentence_transformers import SentenceTransformer, util
4
+ import openai
5
+ from datetime import datetime
6
+
7
+ # --- НАСТРОЙКИ СТРАНИЦЫ ---
8
+ st.set_page_config(layout="wide", page_title="SEO Intent Analyzer Pro")
9
+
10
+ # --- КЭШИРОВАНИЕ МОДЕЛИ (Чтобы не загружать 400мб каждый раз) ---
11
+ @st.cache_resource
12
+ def load_model():
13
+ return SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2')
14
+
15
+ try:
16
+ model = load_model()
17
+ except Exception as e:
18
+ st.error(f"Ошибка загрузки модели: {e}")
19
+
20
+ # --- ИНТЕРФЕЙС: БОКОВАЯ ПАНЕЛЬ ---
21
+ st.sidebar.title("⚙️ Настройки")
22
+
23
+ language = st.sidebar.selectbox(
24
+ "Язык анализа",
25
+ ["English", "Hindi", "Spanish", "Bengali"]
26
+ )
27
+
28
+ api_key = st.sidebar.text_input("OpenAI API Key (для рекомендаций)", type="password")
29
+ target_keyword = st.sidebar.text_input("Целевой Интент / Ключ", "online casino guide")
30
+
31
+ st.sidebar.markdown("---")
32
+ st.sidebar.info("Загрузите тексты конкурентов и свой текст, затем нажмите 'Анализировать'.")
33
+
34
+ # --- ИНТЕРФЕЙС: ОСНОВНАЯ ЧАСТЬ ---
35
+ st.title("🚀 Анализатор Интента (SBERT + AI)")
36
+
37
+ col1, col2 = st.columns(2)
38
+
39
+ with col1:
40
+ st.subheader("📝 Ваш Текст")
41
+ user_text = st.text_area("Вставьте ваш контент сюда", height=400)
42
+
43
+ with col2:
44
+ st.subheader("🕵️ Конкуренты")
45
+ # Используем табы для конкурентов, чтобы не загромождать экран
46
+ tabs = st.tabs([f"Конкурент {i+1}" for i in range(5)])
47
+ competitors = []
48
+
49
+ for i, tab in enumerate(tabs):
50
+ with tab:
51
+ comp_text = st.text_area(f"Текст конкурента {i+1}", height=320, key=f"comp_{i}")
52
+ if len(comp_text) > 50:
53
+ competitors.append(comp_text)
54
+
55
+ # --- ЛОГИКА АНАЛИЗА ---
56
+ if st.button("🚀 ЗАПУСТИТЬ АНАЛИЗ", type="primary"):
57
+ if not user_text:
58
+ st.warning("Пожалуйста, введите ваш текст.")
59
+ elif not competitors:
60
+ st.warning("Пожалуйста, добавьте хотя бы одного конкурента.")
61
+ else:
62
+ with st.spinner('Загрузка нейросети и сравнение векторов...'):
63
+ # 1. Анализ SBERT
64
+ user_emb = model.encode(user_text, convert_to_tensor=True)
65
+ comp_embs = [model.encode(c, convert_to_tensor=True) for c in competitors]
66
+
67
+ # Средний вектор конкурентов
68
+ avg_comp_emb = np.mean([c.cpu().numpy() for c in comp_embs], axis=0)
69
+
70
+ # Сходство
71
+ similarity = util.cos_sim(user_emb, avg_comp_emb).item() * 100
72
+
73
+ # 2. Поиск упущенных аспектов (Gap Analysis)
74
+ user_sentences = user_text.split('.')
75
+ # Собираем все предложения конкурентов в кучу
76
+ comp_sentences_flat = []
77
+ for c in competitors:
78
+ comp_sentences_flat.extend([s for s in c.split('.') if len(s) > 30])
79
+
80
+ # Кодируем предложения
81
+ user_sent_embs = model.encode(user_sentences, convert_to_tensor=True)
82
+ comp_sent_embs = model.encode(comp_sentences_flat, convert_to_tensor=True)
83
+
84
+ # Матрица схожести
85
+ cos_scores = util.cos_sim(comp_sent_embs, user_sent_embs)
86
+
87
+ missing_aspects = []
88
+ # Если предложение конкурента не похоже ни на одно наше (score < 0.45)
89
+ for idx, scores in enumerate(cos_scores):
90
+ if scores.max() < 0.45:
91
+ missing_aspects.append(comp_sentences_flat[idx].strip())
92
+
93
+ # Убираем дубли и берем топ-5
94
+ missing_aspects = list(set(missing_aspects))[:5]
95
+
96
+ # 3. AI Рекомендации
97
+ recommendations = []
98
+ if api_key and missing_aspects:
99
+ openai.api_key = api_key
100
+ status_text = st.empty()
101
+ status_text.text("Генерация рекомендаций через GPT...")
102
+
103
+ for aspect in missing_aspects:
104
+ prompt = f"""
105
+ Role: Expert SEO Copywriter.
106
+ Language: {language}.
107
+ Task: My competitors mention: "{aspect}", but I missed it.
108
+ Action: Write a paragraph (HTML format) to insert into my article to cover this topic.
109
+ """
110
+ try:
111
+ response = openai.ChatCompletion.create(
112
+ model="gpt-3.5-turbo",
113
+ messages=[{"role": "user", "content": prompt}],
114
+ max_tokens=300
115
+ )
116
+ recommendations.append(response.choices[0].message.content)
117
+ except Exception as e:
118
+ st.error(f"AI Error: {e}")
119
+ status_text.empty()
120
+
121
+ # --- ВЫВОД РЕЗУЛЬТАТОВ ---
122
+ st.divider()
123
+ st.header("📊 Результаты Анализа")
124
+
125
+ # Метрики
126
+ m1, m2, m3 = st.columns(3)
127
+ m1.metric("Сходство с Топом", f"{similarity:.1f}%")
128
+ m2.metric("Длина вашего текста", f"{len(user_text.split())} слов")
129
+ m3.metric("Среднее у конкурентов", f"{int(np.mean([len(c.split()) for c in competitors]))} слов")
130
+
131
+ # Визуализация прогресса
132
+ st.write("Шкала раскрытия интента:")
133
+ st.progress(min(int(similarity), 100))
134
+
135
+ # Таблица сравнения
136
+ col_res1, col_res2 = st.columns(2)
137
+
138
+ with col_res1:
139
+ st.subheader("⚠️ Упущенные аспекты (Gaps)")
140
+ if missing_aspects:
141
+ for gap in missing_aspects:
142
+ st.error(f"У конкурентов: \"{gap}\"")
143
+ else:
144
+ st.success("Явных пробелов в интенте не найдено!")
145
+
146
+ with col_res2:
147
+ st.subheader("💡 Рекомендации к внедрению")
148
+ if recommendations:
149
+ for rec in recommendations:
150
+ st.code(rec, language="html")
151
+ st.caption("Скопируйте код выше и вставьте в статью")
152
+ elif not api_key:
153
+ st.info("Введите API Key слева, чтобы получить готовый текст исправлений.")
154
+ else:
155
+ st.info("Рекомендации не требуются.")
156
+
157
+ # Экспорт
158
+ report_text = f"""
159
+ <h1>SEO Report - {target_keyword}</h1>
160
+ <p>Date: {datetime.now()}</p>
161
+ <p>Similarity: {similarity:.2f}%</p>
162
+ <h2>Missing Aspects:</h2>
163
+ <ul>{''.join([f'<li>{m}</li>' for m in missing_aspects])}</ul>
164
+ <h2>AI Recommendations:</h2>
165
+ {''.join(recommendations)}
166
+ """
167
+ st.download_button(
168
+ label="📥 Скачать HTML отчет",
169
+ data=report_text,
170
+ file_name="seo_report.html",
171
+ mime="text/html"
172
+ )
173
+