На самом деле много чего добавил. Например все виды моделей, что если если меньше 0,2 вероятность то Not Found ну и вывод всех классов для Андрей

This commit is contained in:
maksim 2024-06-02 16:38:08 +04:00
parent 6ccd3343e9
commit 2787cf59ae
6 changed files with 88 additions and 17 deletions

View File

@ -1,9 +1,10 @@
from typing import Optional from typing import Optional
from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from sqlalchemy import Column, DateTime from sqlalchemy import Column, DateTime, Enum
from sqlalchemy.sql import func from sqlalchemy.sql import func
from datetime import datetime from datetime import datetime
from enums import TypeMood, TypeModel
engine = create_async_engine("sqlite+aiosqlite:///questions.db") engine = create_async_engine("sqlite+aiosqlite:///questions.db")
new_session = async_sessionmaker(engine, expire_on_commit=False) new_session = async_sessionmaker(engine, expire_on_commit=False)
@ -16,7 +17,8 @@ class QuestionOrm(Model):
id: Mapped[int] = mapped_column(primary_key=True) id: Mapped[int] = mapped_column(primary_key=True)
email_user: Mapped[str] email_user: Mapped[str]
type_question: Mapped[bool] type_mood: Mapped[TypeMood] = mapped_column(Enum(TypeMood))
type_model: Mapped[TypeModel] = mapped_column(Enum(TypeModel))
question: Mapped[str] question: Mapped[str]
answer: Mapped[Optional[str]] answer: Mapped[Optional[str]]
question_time: Mapped[datetime] = mapped_column(DateTime, server_default=func.now()) question_time: Mapped[datetime] = mapped_column(DateTime, server_default=func.now())

10
enums.py Normal file
View File

@ -0,0 +1,10 @@
from enum import Enum
class TypeMood(str, Enum):
POSITIVE = "Posititve"
NEGATIVE = "Negative"
class TypeModel(str, Enum):
LSTM = "LSTM"
GRU = "GRU"
CNN = "CNN"

View File

@ -4,8 +4,17 @@ import tensorflow as tf
from keras.src.legacy.preprocessing.text import Tokenizer from keras.src.legacy.preprocessing.text import Tokenizer
from keras.src.utils import pad_sequences from keras.src.utils import pad_sequences
from enums import TypeMood, TypeModel
# Загрузка модели # Загрузка модели
model = tf.keras.models.load_model('.//neural_network/models/model/best_model_lstm_negative.keras') model_lstm_negative = tf.keras.models.load_model('.//neural_network/models/model/best_model_lstm_negative.keras')
model_gru_negative = tf.keras.models.load_model('.//neural_network/models/model/best_model_gru_negative.keras')
model_cnn_negative = tf.keras.models.load_model('.//neural_network/models/model/best_model_cnn_negative.keras')
model_lstm_positive = tf.keras.models.load_model('.//neural_network/models/model/best_model_lstm_positive.keras')
model_gru_positive = tf.keras.models.load_model('.//neural_network/models/model/best_model_gru_positive.keras')
model_cnn_positive= tf.keras.models.load_model('.//neural_network/models/model/best_model_cnn_positive.keras')
# Загрузка токенизатора # Загрузка токенизатора
with open('.//neural_network/tokenization/tokenizer_negative.pickle', 'rb') as handle: with open('.//neural_network/tokenization/tokenizer_negative.pickle', 'rb') as handle:
@ -18,21 +27,31 @@ with open('.//neural_network/classification/class_names_negative.txt', 'r', enco
def preprocess_text(text: str): def preprocess_text(text: str):
# Токенизация текста # Токенизация текста
sequences = tokenizer.texts_to_sequences([text]) sequences = tokenizer.texts_to_sequences([text])
# Преобразование последовательностей в фиксированной длины # Преобразование последовательностей в фиксированной длине
padded_sequences = pad_sequences(sequences, maxlen=90) # 90 - длина последовательности, используемая при обучении padded_sequences = pad_sequences(sequences, maxlen=90) # 90 - длина последовательности, используемая при обучении
return padded_sequences return padded_sequences
def predict_answer(question: str) -> str: def predict_answer(question: str, type_mood: TypeMood, type_model: TypeModel) -> str:
if type_model == TypeModel.LSTM and type_mood == TypeMood.NEGATIVE:
model = model_lstm_negative
elif type_model == TypeModel.LSTM and type_mood == TypeMood.POSITIVE:
model = model_lstm_positive
elif type_model == TypeModel.GRU and type_mood == TypeMood.NEGATIVE:
model = model_gru_negative
elif type_model == TypeModel.GRU and type_mood == TypeMood.POSITIVE:
model = model_gru_positive
elif type_model == TypeModel.CNN and type_mood == TypeMood.NEGATIVE:
model = model_cnn_negative
elif type_model == TypeModel.CNN and type_mood == TypeMood.POSITIVE:
model = model_cnn_positive
else:
raise ValueError("Unsupported model type")
# Предобработка вопроса # Предобработка вопроса
print("Вопрос:", question)
input_data = preprocess_text(question) input_data = preprocess_text(question)
print("Предобработанные данные:", input_data)
# Предсказание # Предсказание
prediction = model.predict(input_data) prediction = model.predict(input_data)[0]
print("Предсказание:", prediction)
# Определение индекса класса с наибольшей вероятностью
predicted_index = np.argmax(prediction[0])
# Получение имени класса # Получение имени класса
predicted_index = np.argmax(prediction)
predicted_class = class_names[predicted_index] predicted_class = class_names[predicted_index]
print("Предсказанный класс:", predicted_class) return predicted_class, prediction
return predicted_class # Возвращаем имя предсказанного класса

View File

@ -3,17 +3,24 @@ from sqlalchemy.orm import joinedload
from datetime import datetime from datetime import datetime
from database import new_session, QuestionOrm from database import new_session, QuestionOrm
from enums import TypeMood, TypeModel
from schemas import SQuestionAdd, SQuestion from schemas import SQuestionAdd, SQuestion
from model import predict_answer from model import predict_answer
class QuestionRepository: class QuestionRepository:
@classmethod @classmethod
async def add_one(cls, data: SQuestionAdd) -> int: async def add_one(cls, data: SQuestionAdd, type_mood: TypeMood, type_model: TypeModel) -> int:
async with new_session() as session: async with new_session() as session:
question_dict = data.model_dump() question_dict = data.model_dump()
# Предсказание ответа с помощью модели # Предсказание ответа с помощью модели
answer = predict_answer(question_dict["question"]) predicted_class, prediction = predict_answer(question_dict["question"], type_mood, type_model)
# Проверка вероятностей классов
if max(prediction) < 0.2:
answer = "Not Found"
else:
answer = predicted_class
question_dict["answer"] = answer question_dict["answer"] = answer
question_dict["question_time"] = datetime.now() question_dict["question_time"] = datetime.now()
@ -41,3 +48,12 @@ class QuestionRepository:
question_models = result.scalars().all() question_models = result.scalars().all()
question_schemas = [SQuestion.model_validate(question_model) for question_model in question_models] question_schemas = [SQuestion.model_validate(question_model) for question_model in question_models]
return question_schemas return question_schemas
@classmethod
async def find_by_email(cls, email_user: str) -> list[SQuestion]:
async with new_session() as session:
query = select(QuestionOrm).where(QuestionOrm.email_user == email_user)
result = await session.execute(query)
question_models = result.scalars().all()
question_schemas = [SQuestion.model_validate(question_model) for question_model in question_models]
return question_schemas

View File

@ -1,6 +1,8 @@
from typing import Annotated from typing import Annotated
from fastapi import APIRouter, Depends from fastapi import APIRouter, Depends
from typing import List
from enums import TypeMood, TypeModel
from repository import QuestionRepository from repository import QuestionRepository
from schemas import SQuestionAdd, SQuestion, SQuestionId from schemas import SQuestionAdd, SQuestion, SQuestionId
@ -9,14 +11,34 @@ router = APIRouter(
tags=["Questions"], tags=["Questions"],
) )
@router.get("/class_negative")
async def get_class_names() -> List[str]:
with open(".//neural_network/classification/class_names_negative.txt", "r", encoding="utf-8") as file:
class_names = [line.strip() for line in file.readlines()]
return class_names
@router.get("/class_positive")
async def get_class_names() -> List[str]:
with open(".//neural_network/classification/class_names_positive.txt", "r", encoding="utf-8") as file:
class_names = [line.strip() for line in file.readlines()]
return class_names
@router.post("") @router.post("")
async def add_question( async def add_question(
question: Annotated[SQuestionAdd, Depends()], question: Annotated[SQuestionAdd, Depends()],
type_mood: TypeMood, # Добавлен параметр type_mood
type_model: TypeModel, # Добавлен параметр type_model
) -> SQuestionId: ) -> SQuestionId:
question_id = await QuestionRepository.add_one(question) question_id = await QuestionRepository.add_one(question, type_mood, type_model) # Передача параметров type_mood и type_model
return {"ok": True, "question_id": question_id} return {"ok": True, "question_id": question_id}
@router.get("") @router.get("")
async def get_questions() -> list[SQuestion]: async def get_questions() -> list[SQuestion]:
questions = await QuestionRepository.find_all() questions = await QuestionRepository.find_all()
return questions return questions
@router.get("/{email_user}")
async def get_questions_by_email(email_user: str) -> list[SQuestion]:
questions = await QuestionRepository.find_by_email(email_user)
return questions

View File

@ -1,10 +1,12 @@
from typing import Optional from typing import Optional
from pydantic import BaseModel, ConfigDict from pydantic import BaseModel, ConfigDict
from datetime import datetime from datetime import datetime
from enums import TypeMood, TypeModel
class SQuestionAdd(BaseModel): class SQuestionAdd(BaseModel):
email_user: str email_user: str
type_question: bool type_mood: TypeMood
type_model: TypeModel
question: str question: str
class SQuestion(SQuestionAdd): class SQuestion(SQuestionAdd):