Spaces:
Sleeping
Sleeping
setup website
Browse files- __pycache__/config.cpython-313.pyc +0 -0
- __pycache__/database.cpython-313.pyc +0 -0
- __pycache__/states.cpython-313.pyc +0 -0
- app.py +34 -0
- config.py +0 -7
- database.py +0 -36
- functions/__pycache__/sentiment.cpython-313.pyc +0 -0
- functions/sentiment.py +3 -34
- handlers/__init__.py +0 -10
- handlers/__pycache__/__init__.cpython-313.pyc +0 -0
- handlers/__pycache__/history.cpython-313.pyc +0 -0
- handlers/__pycache__/sentiment.cpython-313.pyc +0 -0
- handlers/__pycache__/start.cpython-313.pyc +0 -0
- handlers/history.py +0 -18
- handlers/sentiment.py +0 -23
- handlers/start.py +0 -15
- history.db +0 -0
- main.py +0 -34
- requirements.txt +4 -0
- states.py +0 -9
- templates/index.html +41 -0
__pycache__/config.cpython-313.pyc
CHANGED
|
Binary files a/__pycache__/config.cpython-313.pyc and b/__pycache__/config.cpython-313.pyc differ
|
|
|
__pycache__/database.cpython-313.pyc
DELETED
|
Binary file (2.12 kB)
|
|
|
__pycache__/states.cpython-313.pyc
DELETED
|
Binary file (767 Bytes)
|
|
|
app.py
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
from flask import Flask, request, render_template, send_file, jsonify
|
| 3 |
+
import io
|
| 4 |
+
from functions import (
|
| 5 |
+
sentiment_analysis
|
| 6 |
+
)
|
| 7 |
+
import os
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
app = Flask(__name__)
|
| 11 |
+
app.config['UPLOAD_FOLDER'] = 'uploads'
|
| 12 |
+
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)
|
| 13 |
+
|
| 14 |
+
@app.route('/', methods = ['GET', 'POST'])
|
| 15 |
+
def index():
|
| 16 |
+
result_text = None
|
| 17 |
+
result_image = None
|
| 18 |
+
error = None
|
| 19 |
+
|
| 20 |
+
if request.method == 'POST':
|
| 21 |
+
action = request.form.get('action')
|
| 22 |
+
|
| 23 |
+
if action == 'sentiment':
|
| 24 |
+
text = request.form.get('text', '')
|
| 25 |
+
if text:
|
| 26 |
+
result_text = sentiment_analysis(text)
|
| 27 |
+
else:
|
| 28 |
+
error = "Введите текст"
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
return render_template('index.html', result_text=result_text, error=error)
|
| 32 |
+
|
| 33 |
+
if __name__=='__main__':
|
| 34 |
+
app.run(debug=True, host='0.0.0.0', port=5000)
|
config.py
CHANGED
|
@@ -8,15 +8,8 @@ load_dotenv()
|
|
| 8 |
|
| 9 |
BOT_TOKEN = os.getenv("BOT_TOKEN")
|
| 10 |
HF_TOKEN = os.getenv("HF_TOKEN")
|
| 11 |
-
# REPLICATE_API_TOKEN = os.getenv("REPLICATE_API_TOKEN")
|
| 12 |
-
|
| 13 |
|
| 14 |
SENTIMENT_API = "https://huggingface.co/tabularisai/multilingual-sentiment-analysis"
|
| 15 |
model_name = "tabularisai/multilingual-sentiment-analysis"
|
| 16 |
-
# OBJECT_DETECTION_API = "https://api-inference.huggingface.co/models/facebook/detr-resnet-50"
|
| 17 |
-
# TEXT_GEN_API = "https://api-inference.huggingface.co/models/gpt2"
|
| 18 |
-
# SUMMARIZATION_API = "https://api-inference.huggingface.co/models/facebook/bart-large-cnn"
|
| 19 |
-
# IMAGE_COLORIZATION_API = "https://api-inference.huggingface.co/models/johnj/colorization"
|
| 20 |
-
# EMOTION_API = "https://api-inference.huggingface.co/models/harsh3474/face-emotion-recognition"
|
| 21 |
|
| 22 |
headers = {"Authorization": f"Bearer {HF_TOKEN}"}
|
|
|
|
| 8 |
|
| 9 |
BOT_TOKEN = os.getenv("BOT_TOKEN")
|
| 10 |
HF_TOKEN = os.getenv("HF_TOKEN")
|
|
|
|
|
|
|
| 11 |
|
| 12 |
SENTIMENT_API = "https://huggingface.co/tabularisai/multilingual-sentiment-analysis"
|
| 13 |
model_name = "tabularisai/multilingual-sentiment-analysis"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
|
| 15 |
headers = {"Authorization": f"Bearer {HF_TOKEN}"}
|
database.py
DELETED
|
@@ -1,36 +0,0 @@
|
|
| 1 |
-
import sqlite3
|
| 2 |
-
import datetime
|
| 3 |
-
|
| 4 |
-
DB_NAME= "history.db"
|
| 5 |
-
|
| 6 |
-
def init_db():
|
| 7 |
-
conn=sqlite3.connect(DB_NAME)
|
| 8 |
-
c=conn.cursor()
|
| 9 |
-
c.execute('''CREATE TABLE IF NOT EXISTS history
|
| 10 |
-
(id INTEGER PRIMARY KEY AUTOINCREMENT,
|
| 11 |
-
user_id INTEGER,
|
| 12 |
-
command TEXT,
|
| 13 |
-
input TEXT,
|
| 14 |
-
result TEXT,
|
| 15 |
-
timestamp TEXT)
|
| 16 |
-
''')
|
| 17 |
-
conn.commit()
|
| 18 |
-
conn.close()
|
| 19 |
-
|
| 20 |
-
def add_record(user_id, command, input_data, result):
|
| 21 |
-
conn=sqlite3.connect(DB_NAME)
|
| 22 |
-
c = conn.cursor()
|
| 23 |
-
timestamp = datetime.datetime.now().isoformat()
|
| 24 |
-
c.execute("INSERT INTO history (user_id, command, input, result, timestamp) VALUES (?, ?, ?, ?, ?)",
|
| 25 |
-
(user_id, command, input_data, result, timestamp))
|
| 26 |
-
conn.commit()
|
| 27 |
-
conn.close()
|
| 28 |
-
|
| 29 |
-
def get_history(user_id, limit=10):
|
| 30 |
-
conn = sqlite3.connect(DB_NAME)
|
| 31 |
-
c= conn.cursor()
|
| 32 |
-
c.execute("SELECT command, input, result, timestamp FROM history WHERE user_id = ? ORDER BY time stamp DESC LIMIT ?",
|
| 33 |
-
(user_id, limit))
|
| 34 |
-
rows = c.fetchall()
|
| 35 |
-
conn.close()
|
| 36 |
-
return rows
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
functions/__pycache__/sentiment.cpython-313.pyc
CHANGED
|
Binary files a/functions/__pycache__/sentiment.cpython-313.pyc and b/functions/__pycache__/sentiment.cpython-313.pyc differ
|
|
|
functions/sentiment.py
CHANGED
|
@@ -4,32 +4,10 @@ from transformers import AutoTokenizer, AutoModelForSequenceClassification
|
|
| 4 |
import torch
|
| 5 |
|
| 6 |
|
| 7 |
-
# import os
|
| 8 |
-
# # Отключаем все прокси-переменные
|
| 9 |
-
# os.environ.pop('HTTP_PROXY', None)
|
| 10 |
-
# os.environ.pop('HTTPS_PROXY', None)
|
| 11 |
-
# os.environ.pop('http_proxy', None)
|
| 12 |
-
# os.environ.pop('https_proxy', None)
|
| 13 |
-
# os.environ.pop('ALL_PROXY', None)
|
| 14 |
-
|
| 15 |
-
# async def sentiment_analysis(text:str)->str:
|
| 16 |
-
# payload = {"inputs":text}
|
| 17 |
-
# try:
|
| 18 |
-
# response = requests.post(SENTIMENT_API, headers=headers, json=payload)
|
| 19 |
-
# result = response.json()
|
| 20 |
-
# if isinstance(result, list) and len(result)>0:
|
| 21 |
-
# labels = result[0]
|
| 22 |
-
# best = max(labels, key=lambda x: x['score'])
|
| 23 |
-
# label_map = {"LABEL_0":"негативный", "LABEL_1": "нейтральный", "LABEL_2": "позитивный"}
|
| 24 |
-
# return label_map.get(best['label'], best['label'])
|
| 25 |
-
# return "не удалось определить"
|
| 26 |
-
# except Exception as e:
|
| 27 |
-
# return f"Error: {str(e)}"
|
| 28 |
-
|
| 29 |
tokenizer = AutoTokenizer.from_pretrained(model_name)
|
| 30 |
model = AutoModelForSequenceClassification.from_pretrained(model_name)
|
| 31 |
|
| 32 |
-
|
| 33 |
'''принимает строку, возвращает тональность'''
|
| 34 |
try:
|
| 35 |
inputs = tokenizer(text, return_tensors="pt", truncation=True, padding=True, max_length=512)
|
|
@@ -37,9 +15,9 @@ async def sentiment_analysis(text)->str:
|
|
| 37 |
outputs = model(**inputs)
|
| 38 |
#вероятности классов
|
| 39 |
probabilities = torch.nn.functional.softmax(outputs.logits, dim=-1)
|
| 40 |
-
pred_class = torch.argmax(probabilities, dim=-1).
|
| 41 |
|
| 42 |
-
if pred_class <=1:
|
| 43 |
return "Негативный"
|
| 44 |
elif pred_class ==2:
|
| 45 |
return "Нейтральный"
|
|
@@ -48,12 +26,3 @@ async def sentiment_analysis(text)->str:
|
|
| 48 |
|
| 49 |
except Exception as e:
|
| 50 |
return f"Error: {str(e)}"
|
| 51 |
-
#
|
| 52 |
-
#
|
| 53 |
-
# texts = [
|
| 54 |
-
# "I absolutely love the new design of this app!", "The customer service was disappointing.", "The weather is fine, nothing special.",
|
| 55 |
-
# "Я в восторге от этого нового гаджета!", "Этот сервис оставил у меня только разочарование.", "Встреча была обычной, ничего особенного.",
|
| 56 |
-
# ]
|
| 57 |
-
#
|
| 58 |
-
# for text, sentiment in zip(texts, sentiment_analysis(texts)):
|
| 59 |
-
# print(f"Text: {text}\nSentiment: {sentiment}\n")
|
|
|
|
| 4 |
import torch
|
| 5 |
|
| 6 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
tokenizer = AutoTokenizer.from_pretrained(model_name)
|
| 8 |
model = AutoModelForSequenceClassification.from_pretrained(model_name)
|
| 9 |
|
| 10 |
+
def sentiment_analysis(text)->str:
|
| 11 |
'''принимает строку, возвращает тональность'''
|
| 12 |
try:
|
| 13 |
inputs = tokenizer(text, return_tensors="pt", truncation=True, padding=True, max_length=512)
|
|
|
|
| 15 |
outputs = model(**inputs)
|
| 16 |
#вероятности классов
|
| 17 |
probabilities = torch.nn.functional.softmax(outputs.logits, dim=-1)
|
| 18 |
+
pred_class = torch.argmax(probabilities, dim=-1).item()
|
| 19 |
|
| 20 |
+
if pred_class <= 1:
|
| 21 |
return "Негативный"
|
| 22 |
elif pred_class ==2:
|
| 23 |
return "Нейтральный"
|
|
|
|
| 26 |
|
| 27 |
except Exception as e:
|
| 28 |
return f"Error: {str(e)}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
handlers/__init__.py
DELETED
|
@@ -1,10 +0,0 @@
|
|
| 1 |
-
from aiogram import Router
|
| 2 |
-
from .sentiment import router as sentiment_router
|
| 3 |
-
from .history import router as history_router
|
| 4 |
-
from .start import router as start_router
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
def register_all_handlers(dp:Router):
|
| 8 |
-
dp.include_router(start_router)
|
| 9 |
-
dp.include_router(sentiment_router)
|
| 10 |
-
dp.include_router(history_router)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
handlers/__pycache__/__init__.cpython-313.pyc
DELETED
|
Binary file (675 Bytes)
|
|
|
handlers/__pycache__/history.cpython-313.pyc
DELETED
|
Binary file (1.19 kB)
|
|
|
handlers/__pycache__/sentiment.cpython-313.pyc
DELETED
|
Binary file (1.8 kB)
|
|
|
handlers/__pycache__/start.cpython-313.pyc
DELETED
|
Binary file (760 Bytes)
|
|
|
handlers/history.py
DELETED
|
@@ -1,18 +0,0 @@
|
|
| 1 |
-
from aiogram import Router
|
| 2 |
-
from aiogram.types import Message
|
| 3 |
-
from aiogram.filters import Command
|
| 4 |
-
from database import get_history
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
router = Router()
|
| 8 |
-
|
| 9 |
-
@router.message("history")
|
| 10 |
-
async def cmd_history(message:Message):
|
| 11 |
-
rows = get_history(message.from_user.id)
|
| 12 |
-
if not rows:
|
| 13 |
-
await message.answer("история пуста")
|
| 14 |
-
return
|
| 15 |
-
answer = "Последние 10 действий:\n"
|
| 16 |
-
for cmd, inp, res, ts in rows:
|
| 17 |
-
answer+= f"- {ts[:16]} | {cmd} | {inp[:15]} \n"
|
| 18 |
-
await message.answer(answer[:20])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
handlers/sentiment.py
DELETED
|
@@ -1,23 +0,0 @@
|
|
| 1 |
-
from aiogram.types import Message
|
| 2 |
-
from aiogram.filters import Command
|
| 3 |
-
from aiogram import Router, F
|
| 4 |
-
from aiogram.fsm.context import FSMContext
|
| 5 |
-
from functions import sentiment_analysis
|
| 6 |
-
from database import add_record
|
| 7 |
-
from states import MemeState
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
# для связывания URL-адресов с кодом
|
| 11 |
-
router = Router()
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
@router.message(Command("sentiment"))
|
| 15 |
-
async def cmd_sentiment(message:Message, state: FSMContext):
|
| 16 |
-
await state.set_state(MemeState.waiting_text)
|
| 17 |
-
await message.answer("Напишите текст для анализа")
|
| 18 |
-
|
| 19 |
-
@router.message(MemeState.waiting_text, F.text)
|
| 20 |
-
async def analyze(msg:Message, state: FSMContext):
|
| 21 |
-
result = await sentiment_analysis(msg.text)
|
| 22 |
-
await msg.answer(f"Тональность {result}")
|
| 23 |
-
add_record(msg.from_user.id, "sentiment", msg.text[:500], result)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
handlers/start.py
DELETED
|
@@ -1,15 +0,0 @@
|
|
| 1 |
-
from aiogram import Router
|
| 2 |
-
from aiogram.types import Message
|
| 3 |
-
from aiogram.filters import Command
|
| 4 |
-
|
| 5 |
-
router = Router()
|
| 6 |
-
|
| 7 |
-
@router.message(Command("start"))
|
| 8 |
-
async def start(message:Message):
|
| 9 |
-
text =("Hello! Я нейросетевой бот.\n"
|
| 10 |
-
"Мои команды:\n"
|
| 11 |
-
"/start\n"
|
| 12 |
-
"/help\n"
|
| 13 |
-
"/sentiment\n"
|
| 14 |
-
"/history\n")
|
| 15 |
-
await message.answer(text)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
history.db
DELETED
|
Binary file (12.3 kB)
|
|
|
main.py
DELETED
|
@@ -1,34 +0,0 @@
|
|
| 1 |
-
import asyncio
|
| 2 |
-
import logging
|
| 3 |
-
from aiogram import Bot, Dispatcher
|
| 4 |
-
from aiogram.filters import Command
|
| 5 |
-
from aiogram.types import Message
|
| 6 |
-
from config import BOT_TOKEN
|
| 7 |
-
from database import init_db
|
| 8 |
-
from handlers import register_all_handlers
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
# @dp.message(F.text)
|
| 12 |
-
# async def echo(message:Message):
|
| 13 |
-
# await message.answer(f"{message.text}")
|
| 14 |
-
#
|
| 15 |
-
# @dp.message(F.sticker)
|
| 16 |
-
# async def echo_sticker(message: Message):
|
| 17 |
-
# await message.answer_sticker(sticker=message.sticker.file_id)
|
| 18 |
-
#
|
| 19 |
-
# @dp.message(F.photo)
|
| 20 |
-
# async def echo_photo(message:Message):
|
| 21 |
-
# photo = message.photo[-1]
|
| 22 |
-
# await message.answer_photo(photo.file_id, caption=message.caption)
|
| 23 |
-
|
| 24 |
-
async def main():
|
| 25 |
-
init_db()
|
| 26 |
-
bot = Bot(token=BOT_TOKEN)
|
| 27 |
-
dp = Dispatcher()
|
| 28 |
-
register_all_handlers(dp)
|
| 29 |
-
logging.basicConfig(level=logging.INFO)
|
| 30 |
-
await dp.start_polling(bot)
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
if __name__ == "__main__":
|
| 34 |
-
asyncio.run(main())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
requirements.txt
CHANGED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
flask
|
| 2 |
+
torch
|
| 3 |
+
transformers
|
| 4 |
+
dotenv
|
states.py
DELETED
|
@@ -1,9 +0,0 @@
|
|
| 1 |
-
from aiogram.fsm.state import StatesGroup, State
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
class StyleTransferStates(StatesGroup):
|
| 5 |
-
waiting_content = State()
|
| 6 |
-
waiting_style = State()
|
| 7 |
-
|
| 8 |
-
class MemeState(StatesGroup):
|
| 9 |
-
waiting_text=State()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
templates/index.html
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<title>Нейросетевой помощник</title>
|
| 6 |
+
<style>
|
| 7 |
+
body { font-family: Arial; margin:40; }
|
| 8 |
+
.function-box { border: 1px solid #ccc; padding: 15px; margin-bottom:20px; border-radius: 8px; }
|
| 9 |
+
.result { background: #f0f0f0; padding: 10px; border-radius: 5px; margin-top: 10px;}
|
| 10 |
+
.error {color: red;}
|
| 11 |
+
</style>
|
| 12 |
+
</head>
|
| 13 |
+
<body>
|
| 14 |
+
<h1>Нейросетевой помощник</h1>
|
| 15 |
+
<p>Выберите функцию и введите данные</p>
|
| 16 |
+
|
| 17 |
+
{% if error %}
|
| 18 |
+
<div class="error"{{ error }}</div>
|
| 19 |
+
{% endif %}
|
| 20 |
+
|
| 21 |
+
<form method="POST" enctype="multipart/form-data">
|
| 22 |
+
<div class="function-box">
|
| 23 |
+
<h3>Текстовые функции</h3>
|
| 24 |
+
<select name="action">
|
| 25 |
+
<option value="sentiment">Анализ тональности</option>
|
| 26 |
+
</select>
|
| 27 |
+
<br><br>
|
| 28 |
+
<textarea name="text" rows="4" cols="50" placeholder="Введите текст..."></textarea>
|
| 29 |
+
<br>
|
| 30 |
+
<input type="submit" value="Отправить">
|
| 31 |
+
</div>
|
| 32 |
+
</form>
|
| 33 |
+
|
| 34 |
+
{% if result_text %}
|
| 35 |
+
<div class="result">
|
| 36 |
+
<h3>Результат</h3>
|
| 37 |
+
<p>{{ result_text }}</p>
|
| 38 |
+
</div>
|
| 39 |
+
{% endif %}
|
| 40 |
+
</body>
|
| 41 |
+
</html>
|