Update app.py
Browse files
app.py
CHANGED
|
@@ -1,60 +1,18 @@
|
|
| 1 |
-
|
| 2 |
from transformers import AutoTokenizer, AutoModelForSequenceClassification
|
| 3 |
-
from pydantic import BaseModel
|
| 4 |
import torch
|
| 5 |
|
| 6 |
# Загрузка модели и токенизатора
|
| 7 |
tokenizer = AutoTokenizer.from_pretrained("MrAlexGov/is-it-job-ru-q1a8e-lkjvk")
|
| 8 |
model = AutoModelForSequenceClassification.from_pretrained("MrAlexGov/is-it-job-ru-q1a8e-lkjvk")
|
| 9 |
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
)
|
| 15 |
-
|
| 16 |
-
# Модель для входных данных
|
| 17 |
-
class TextRequest(BaseModel):
|
| 18 |
-
text: str
|
| 19 |
-
|
| 20 |
-
# Модель для ответа
|
| 21 |
-
class PredictionResponse(BaseModel):
|
| 22 |
-
prediction: str
|
| 23 |
-
is_it_job: bool
|
| 24 |
-
confidence: float
|
| 25 |
-
class_id: int
|
| 26 |
-
|
| 27 |
-
@app.get("/")
|
| 28 |
-
def read_root():
|
| 29 |
-
return {
|
| 30 |
-
"message": "API для классификации IT-вакансий",
|
| 31 |
-
"endpoints": {
|
| 32 |
-
"GET /": "Эта документация",
|
| 33 |
-
"POST /predict": "Классификация текста на предмет IT-вакансии",
|
| 34 |
-
"GET /health": "Проверка статуса API"
|
| 35 |
-
},
|
| 36 |
-
"model_info": {
|
| 37 |
-
"model_name": "is-it-job-ru-q1a8e-lkjvk",
|
| 38 |
-
"task": "Sequence Classification",
|
| 39 |
-
"description": "Модель определяет, относится ли текст к IT-вакансии"
|
| 40 |
-
}
|
| 41 |
-
}
|
| 42 |
-
|
| 43 |
-
@app.post("/predict", response_model=PredictionResponse)
|
| 44 |
-
def predict(request: TextRequest):
|
| 45 |
-
"""
|
| 46 |
-
Классифицирует текст на предмет того, является ли он IT-вакансией
|
| 47 |
|
| 48 |
-
- **text**: Текст для классификации (например, описание вакансии)
|
| 49 |
-
|
| 50 |
-
Возвращает:
|
| 51 |
-
- **prediction**: "IT-вакансия" или "Не IT-вакансия"
|
| 52 |
-
- **is_it_job**: Булево значение (True/False)
|
| 53 |
-
- **confidence**: Уверенность модели (от 0 до 1)
|
| 54 |
-
- **class_id**: ID класса (0 или 1)
|
| 55 |
-
"""
|
| 56 |
# Токенизация текста
|
| 57 |
-
inputs = tokenizer(
|
| 58 |
|
| 59 |
# Получение предсказания
|
| 60 |
with torch.no_grad():
|
|
@@ -64,23 +22,69 @@ def predict(request: TextRequest):
|
|
| 64 |
confidence = probabilities[0][prediction_id].item()
|
| 65 |
|
| 66 |
# Определение меток классов
|
| 67 |
-
# Обычно: 0 - не IT-вакансия, 1 - IT-вакансия
|
| 68 |
-
# Уточните метки в соответствии с вашей моделью
|
| 69 |
is_it_job = prediction_id == 1
|
| 70 |
prediction_label = "IT-вакансия" if is_it_job else "Не IT-вакансия"
|
| 71 |
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 77 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 78 |
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
return {
|
| 83 |
-
"status": "healthy",
|
| 84 |
-
"model_loaded": True,
|
| 85 |
-
"model_name": "MrAlexGov/is-it-job-ru-q1a8e-lkjvk"
|
| 86 |
-
}
|
|
|
|
| 1 |
+
import gradio as gr
|
| 2 |
from transformers import AutoTokenizer, AutoModelForSequenceClassification
|
|
|
|
| 3 |
import torch
|
| 4 |
|
| 5 |
# Загрузка модели и токенизатора
|
| 6 |
tokenizer = AutoTokenizer.from_pretrained("MrAlexGov/is-it-job-ru-q1a8e-lkjvk")
|
| 7 |
model = AutoModelForSequenceClassification.from_pretrained("MrAlexGov/is-it-job-ru-q1a8e-lkjvk")
|
| 8 |
|
| 9 |
+
def classify_text(text):
|
| 10 |
+
"""Классифицирует текст на IT/не IT вакансию"""
|
| 11 |
+
if not text.strip():
|
| 12 |
+
return "Пожалуйста, введите текст для классификации"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
# Токенизация текста
|
| 15 |
+
inputs = tokenizer(text, return_tensors="pt", truncation=True, max_length=512)
|
| 16 |
|
| 17 |
# Получение предсказания
|
| 18 |
with torch.no_grad():
|
|
|
|
| 22 |
confidence = probabilities[0][prediction_id].item()
|
| 23 |
|
| 24 |
# Определение меток классов
|
|
|
|
|
|
|
| 25 |
is_it_job = prediction_id == 1
|
| 26 |
prediction_label = "IT-вакансия" if is_it_job else "Не IT-вакансия"
|
| 27 |
|
| 28 |
+
# Форматирование результата
|
| 29 |
+
result = f"""
|
| 30 |
+
🎯 **Результат классификации:**
|
| 31 |
+
|
| 32 |
+
📝 **Текст:** {text[:100]}...
|
| 33 |
+
|
| 34 |
+
🏷️ **Классификация:** {prediction_label}
|
| 35 |
+
🔍 **Уверенность модели:** {confidence:.2%}
|
| 36 |
+
💼 **Это IT-вакансия:** {"Да" if is_it_job else "Нет"}
|
| 37 |
+
🔢 **ID класса:** {prediction_id}
|
| 38 |
+
|
| 39 |
+
{'✅ Текст относится к IT-вакансии!' if is_it_job else '❌ Текст не относится к IT-вакансии.'}
|
| 40 |
+
"""
|
| 41 |
+
|
| 42 |
+
return result
|
| 43 |
+
|
| 44 |
+
# Создание Gradio интерфейса
|
| 45 |
+
with gr.Blocks(title="IT Job Classifier", theme=gr.themes.Soft()) as demo:
|
| 46 |
+
gr.Markdown("# 🧠 Классификатор IT-вакансий")
|
| 47 |
+
gr.Markdown("Определяет, относится ли текст описания вакансии к IT-сфере")
|
| 48 |
+
|
| 49 |
+
with gr.Row():
|
| 50 |
+
with gr.Column():
|
| 51 |
+
text_input = gr.Textbox(
|
| 52 |
+
label="Введите текст вакансии",
|
| 53 |
+
placeholder="Пример: Ищем Senior Python разработчика для создания микросервисов...",
|
| 54 |
+
lines=5
|
| 55 |
+
)
|
| 56 |
+
submit_btn = gr.Button("🔍 Классифицировать", variant="primary")
|
| 57 |
+
|
| 58 |
+
with gr.Column():
|
| 59 |
+
output = gr.Markdown(label="Результат")
|
| 60 |
+
|
| 61 |
+
# Примеры для быстрого тестирования
|
| 62 |
+
examples = [
|
| 63 |
+
["Ищем Senior Python разработчика с опытом работы от 3 лет для создания микросервисо�� на Django и FastAPI. Требуется знание Docker, PostgreSQL, Redis."],
|
| 64 |
+
["Требуется менеджер по продажам IT-оборудования. Обязанности: поиск клиентов, проведение переговоров, заключение договоров."],
|
| 65 |
+
["Нужен DevOps инженер для настройки CI/CD пайплайнов, работы с Kubernetes и мониторинга инфраструктуры в AWS."],
|
| 66 |
+
["Ищем бухгалтера для ведения финансовой отчетности компании. Требования: знание 1С, опыт работы от 2 лет."]
|
| 67 |
+
]
|
| 68 |
+
|
| 69 |
+
gr.Examples(
|
| 70 |
+
examples=examples,
|
| 71 |
+
inputs=text_input,
|
| 72 |
+
outputs=output,
|
| 73 |
+
fn=classify_text,
|
| 74 |
+
cache_examples=True
|
| 75 |
)
|
| 76 |
+
|
| 77 |
+
# Обработка событий
|
| 78 |
+
submit_btn.click(fn=classify_text, inputs=text_input, outputs=output)
|
| 79 |
+
text_input.submit(fn=classify_text, inputs=text_input, outputs=output)
|
| 80 |
+
|
| 81 |
+
# Информация о модели
|
| 82 |
+
gr.Markdown("---")
|
| 83 |
+
gr.Markdown("### 📊 Информация о модели")
|
| 84 |
+
gr.Markdown(f"**Модель:** `MrAlexGov/is-it-job-ru-q1a8e-lkjvk`")
|
| 85 |
+
gr.Markdown("**Задача:** Классификация текста на IT/не IT вакансии")
|
| 86 |
+
gr.Markdown("**Максимальная длина текста:** 512 токенов")
|
| 87 |
|
| 88 |
+
# Запуск приложения
|
| 89 |
+
if __name__ == "__main__":
|
| 90 |
+
demo.launch(debug=True, share=False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|