mirror of
https://github.com/spbleadersofdigtal/backend.git
synced 2024-11-22 03:16:33 +03:00
added ml, questions submit
This commit is contained in:
parent
2cc1736951
commit
d784e04ff5
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,4 +1,5 @@
|
||||||
!.gitkeep
|
!.gitkeep
|
||||||
|
.idea
|
||||||
|
|
||||||
### Python template
|
### Python template
|
||||||
# Byte-compiled / optimized / DLL files
|
# Byte-compiled / optimized / DLL files
|
||||||
|
|
|
@ -351,4 +351,4 @@
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
OPENAI_KEY = env("OPENAI_KEY")
|
OPENAI_KEY = env("OPENAI_KEY", default="")
|
||||||
|
|
BIN
ml/data.pic
Normal file
BIN
ml/data.pic
Normal file
Binary file not shown.
BIN
ml/index.ann
Normal file
BIN
ml/index.ann
Normal file
Binary file not shown.
|
@ -33,38 +33,37 @@
|
||||||
|
|
||||||
prompts = [
|
prompts = [
|
||||||
"""
|
"""
|
||||||
По тексту ответь или предположи ответ на вопросы в следющем формате:
|
По тексту ответь или предположи ответ на вопросы в следющем формате:
|
||||||
{
|
{
|
||||||
'users': 'Кто будет пользоваться продуктом',
|
'users': 'Кто будет пользоваться продуктом',
|
||||||
'problems': 'Какие проблемы решает продукт',
|
'problems': 'Какие проблемы решает продукт',
|
||||||
'actuality': 'Продолжите предложение: Актуальность проблемы подтверждается тем фактом, что...',
|
'actuality': 'Продолжите предложение: Актуальность проблемы подтверждается тем фактом, что...',
|
||||||
'solve': 'Как решаем эти проблемы',
|
'solve': 'Как решаем эти проблемы',
|
||||||
'works': 'Как работает решение',
|
'works': 'Как работает решение',
|
||||||
}
|
}
|
||||||
""",
|
""",
|
||||||
"""
|
"""
|
||||||
По тексту ответь или предположи ответ на вопросы в следющем формате:
|
По тексту ответь или предположи ответ на вопросы в следющем формате:
|
||||||
{
|
{
|
||||||
'awards': 'Когда проблема будет решена, какова будет ценность для ваших пользователей',
|
'awards': 'Когда проблема будет решена, какова будет ценность для ваших пользователей',
|
||||||
'money': 'На чем проект зарабатывает? сколько и за что ему платят клиенты',
|
'money': 'На чем проект зарабатывает? сколько и за что ему платят клиенты',
|
||||||
'aims': Напиши 3 цели: на месяц, на полгода и год, формат: {'1': цель на месяц, '2': цель на полгода, '3': цель на год},
|
'aims': Напиши 3 цели: на месяц, на полгода и год, формат: {'1': цель на месяц, '2': цель на полгода, '3': цель на год},
|
||||||
'investments_sold': 'На что потратить инвестиции под проект',
|
'investments_sold': 'На что потратить инвестиции под проект',
|
||||||
'financial_indicators': 'Напиши финансовые показатели проекта'
|
'financial_indicators': 'Напиши финансовые показатели проекта'
|
||||||
}
|
}
|
||||||
""",
|
""",
|
||||||
"""
|
"""
|
||||||
По тексту ответь или предположи ответ на вопросы в следющем формате:
|
По тексту ответь или предположи ответ на вопросы в следющем формате:
|
||||||
{
|
{
|
||||||
|
|
||||||
'achieve': 'Чего добьется команда после освоения инвестиций',
|
'achieve': 'Чего добьется команда после освоения инвестиций',
|
||||||
'competitors_strength': 'Сильные стороны конкурентов',
|
'competitors_strength': 'Сильные стороны конкурентов',
|
||||||
'competitors_low': 'Слабые стороны конкурентов',
|
'competitors_low': 'Слабые стороны конкурентов',
|
||||||
'advantages': 'Какие могут быть преимущества над конкурентами'
|
'advantages': 'Какие могут быть преимущества над конкурентами'
|
||||||
}
|
}
|
||||||
""",
|
""",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
openai.api_key = KEY
|
openai.api_key = KEY
|
||||||
|
|
||||||
assertions = [
|
assertions = [
|
||||||
|
@ -105,15 +104,21 @@ def create_hints(description: str, stage: int):
|
||||||
content["aims"] = [
|
content["aims"] = [
|
||||||
{
|
{
|
||||||
"aim": content["aims"]["1"],
|
"aim": content["aims"]["1"],
|
||||||
"date": datetime.datetime.now() + datetime.timedelta(days=30),
|
"date": (
|
||||||
|
datetime.datetime.now() + datetime.timedelta(days=30)
|
||||||
|
).isoformat(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"aim": content["aims"]["2"],
|
"aim": content["aims"]["2"],
|
||||||
"date": datetime.datetime.now() + datetime.timedelta(days=180),
|
"date": (
|
||||||
|
datetime.datetime.now() + datetime.timedelta(days=180)
|
||||||
|
).isoformat(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"aim": content["aims"]["3"],
|
"aim": content["aims"]["3"],
|
||||||
"date": datetime.datetime.now() + datetime.timedelta(days=365),
|
"date": (
|
||||||
|
datetime.datetime.now() + datetime.timedelta(days=365)
|
||||||
|
).isoformat(),
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
result = []
|
result = []
|
||||||
|
|
49
ml/search.py
Normal file
49
ml/search.py
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
from annoy import AnnoyIndex
|
||||||
|
from sentence_transformers import SentenceTransformer
|
||||||
|
import pickle
|
||||||
|
|
||||||
|
model = None
|
||||||
|
data = None
|
||||||
|
index = None
|
||||||
|
|
||||||
|
|
||||||
|
def get_model():
|
||||||
|
global model
|
||||||
|
if not model:
|
||||||
|
model = SentenceTransformer("sentence-transformers/LaBSE")
|
||||||
|
return model
|
||||||
|
|
||||||
|
|
||||||
|
def get_data():
|
||||||
|
global data
|
||||||
|
if not data:
|
||||||
|
with open("ml/data.pic", "rb") as file:
|
||||||
|
data = pickle.load(file)
|
||||||
|
print(len(data))
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def get_index():
|
||||||
|
global index
|
||||||
|
if not index:
|
||||||
|
index = AnnoyIndex(768, "angular")
|
||||||
|
index.load("ml/index.ann")
|
||||||
|
return index
|
||||||
|
|
||||||
|
|
||||||
|
def search(search_string):
|
||||||
|
embs = get_model().encode([search_string])[0]
|
||||||
|
indexes = get_index().get_nns_by_vector(embs, 5)
|
||||||
|
res = []
|
||||||
|
for i in indexes:
|
||||||
|
res.append(get_data()[i])
|
||||||
|
return list(
|
||||||
|
map(
|
||||||
|
lambda x: {
|
||||||
|
"logo": x["image"],
|
||||||
|
"name": x["name"],
|
||||||
|
"description": x["description"],
|
||||||
|
},
|
||||||
|
res,
|
||||||
|
)
|
||||||
|
)
|
|
@ -1,7 +1,16 @@
|
||||||
|
from dateutil.parser import parse
|
||||||
|
from django.core.files.uploadedfile import InMemoryUploadedFile, TemporaryUploadedFile
|
||||||
from drf_spectacular.utils import extend_schema_field
|
from drf_spectacular.utils import extend_schema_field
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
from rest_framework.generics import get_object_or_404
|
||||||
|
|
||||||
from pitch_deck_generator.decks.models import PitchDeck, Question, QuestionDeckHint
|
from pitch_deck_generator.decks.models import (
|
||||||
|
PitchDeck,
|
||||||
|
Question,
|
||||||
|
QuestionDeckHint,
|
||||||
|
QuestionAnswer,
|
||||||
|
QuestionAnswerPhoto,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class BasePitchDeckSerializer(serializers.ModelSerializer):
|
class BasePitchDeckSerializer(serializers.ModelSerializer):
|
||||||
|
@ -35,12 +44,17 @@ class QuestionSerializer(serializers.ModelSerializer):
|
||||||
@extend_schema_field(HintSerializer)
|
@extend_schema_field(HintSerializer)
|
||||||
def get_hint(self, obj):
|
def get_hint(self, obj):
|
||||||
if obj.hint:
|
if obj.hint:
|
||||||
|
question_id = (
|
||||||
|
self.context["view"].kwargs["question_id"]
|
||||||
|
if "question_id" in self.context["view"].kwargs
|
||||||
|
else 1
|
||||||
|
)
|
||||||
if q := QuestionDeckHint.objects.filter(
|
if q := QuestionDeckHint.objects.filter(
|
||||||
question_id=self.context["kwargs"]["question"],
|
question_id=question_id,
|
||||||
deck_id=self.context["kwargs"]["deck"],
|
deck_id=self.context["view"].kwargs["deck_id"],
|
||||||
):
|
):
|
||||||
return q.first().hint
|
return q.first().hint
|
||||||
return ""
|
return {}
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@extend_schema_field(serializers.IntegerField)
|
@extend_schema_field(serializers.IntegerField)
|
||||||
|
@ -51,4 +65,165 @@ def get_next_id(self, obj):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Question
|
model = Question
|
||||||
fields = ["id", "text", "hint", "required", "params", "next_id"]
|
fields = ["id", "text", "hint", "required", "type", "params", "next_id"]
|
||||||
|
|
||||||
|
|
||||||
|
class AnswerSerializer(serializers.ModelSerializer):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
file_fields = kwargs.pop("file_fields", None)
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
if file_fields:
|
||||||
|
field_update_dict = {
|
||||||
|
field: serializers.FileField(required=False, write_only=True)
|
||||||
|
for field in file_fields
|
||||||
|
}
|
||||||
|
self.fields.update(**field_update_dict)
|
||||||
|
|
||||||
|
file = serializers.FileField(allow_null=True, required=False)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = QuestionAnswer
|
||||||
|
fields = ["answer", "deck", "question", "file"]
|
||||||
|
extra_kwargs = {
|
||||||
|
"deck": {"read_only": True},
|
||||||
|
"question": {"read_only": True},
|
||||||
|
}
|
||||||
|
|
||||||
|
def validate(self, data):
|
||||||
|
answer = data["answer"]
|
||||||
|
question = get_object_or_404(
|
||||||
|
Question, id=self.context["view"].kwargs["question_id"]
|
||||||
|
)
|
||||||
|
deck = get_object_or_404(PitchDeck, id=self.context["view"].kwargs["deck_id"])
|
||||||
|
question_type = question.type
|
||||||
|
params = question.params if question.params else {}
|
||||||
|
match question_type:
|
||||||
|
case "text":
|
||||||
|
if type(answer) is not str:
|
||||||
|
raise serializers.ValidationError("Incorrect type")
|
||||||
|
if "max_length" in params:
|
||||||
|
if len(answer) > params["max_length"]:
|
||||||
|
raise serializers.ValidationError("Text is too long")
|
||||||
|
case "number":
|
||||||
|
if type(answer) is not str:
|
||||||
|
raise serializers.ValidationError("Incorrect type")
|
||||||
|
case "text_array":
|
||||||
|
if type(answer) is not list:
|
||||||
|
raise serializers.ValidationError("Incorrect type")
|
||||||
|
|
||||||
|
if any([type(x) is not str for x in answer]):
|
||||||
|
raise serializers.ValidationError("Incorrect type")
|
||||||
|
case "range":
|
||||||
|
slug = params["slug"]
|
||||||
|
if slug not in answer:
|
||||||
|
raise serializers.ValidationError("Value to found")
|
||||||
|
if not isinstance(answer[slug], (int, float)):
|
||||||
|
raise serializers.ValidationError("Incorrect type")
|
||||||
|
if not (params["min_value"] <= answer[slug] <= params["max_value"]):
|
||||||
|
raise serializers.ValidationError("Number is too big or too small")
|
||||||
|
case "multiple_range":
|
||||||
|
for slug in [x["slug"] for x in params["scrollbars"]]:
|
||||||
|
if slug not in answer:
|
||||||
|
raise serializers.ValidationError(f"Value {slug} to found")
|
||||||
|
if not isinstance(answer[slug], (int, float)):
|
||||||
|
raise serializers.ValidationError(f"Incorrect {slug} type")
|
||||||
|
if not (params["min_value"] <= answer[slug] <= params["max_value"]):
|
||||||
|
raise serializers.ValidationError(
|
||||||
|
f"Number is too big or too small for {slug}"
|
||||||
|
)
|
||||||
|
case "select":
|
||||||
|
if answer not in params["options"]:
|
||||||
|
raise serializers.ValidationError("No such option")
|
||||||
|
case "date":
|
||||||
|
try:
|
||||||
|
parse(answer)
|
||||||
|
except ValueError:
|
||||||
|
raise serializers.ValidationError("Incorrect date type")
|
||||||
|
case "photo":
|
||||||
|
if answer:
|
||||||
|
raise serializers.ValidationError("Answer should be blank")
|
||||||
|
|
||||||
|
if not data["file"]:
|
||||||
|
raise serializers.ValidationError("No file found")
|
||||||
|
case "multiple_photo":
|
||||||
|
if answer:
|
||||||
|
raise serializers.ValidationError("Answer should be blank")
|
||||||
|
for key, value in data.items():
|
||||||
|
if isinstance(value, InMemoryUploadedFile):
|
||||||
|
if "_" not in key:
|
||||||
|
raise serializers.ValidationError(
|
||||||
|
"You should use file_num for file keys"
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
int(key.split("_")[1])
|
||||||
|
except ValueError:
|
||||||
|
raise serializers.ValidationError(
|
||||||
|
"You should use file_num for file keys"
|
||||||
|
)
|
||||||
|
|
||||||
|
case "photo_description":
|
||||||
|
if not data["file"]:
|
||||||
|
raise serializers.ValidationError("No file found")
|
||||||
|
if type(answer) is not str:
|
||||||
|
raise serializers.ValidationError("Incorrect type")
|
||||||
|
if "max_length" in params:
|
||||||
|
if len(answer) > params["max_length"]:
|
||||||
|
raise serializers.ValidationError("Text is too long")
|
||||||
|
case "multiple_photo_description":
|
||||||
|
if type(answer) is not list:
|
||||||
|
raise serializers.ValidationError("Incorrect type")
|
||||||
|
|
||||||
|
if any([type(x) is not str for x in answer]):
|
||||||
|
raise serializers.ValidationError("Incorrect type")
|
||||||
|
|
||||||
|
len_f = 0
|
||||||
|
|
||||||
|
for key, value in data.items():
|
||||||
|
if isinstance(value, TemporaryUploadedFile):
|
||||||
|
if "_" not in key:
|
||||||
|
raise serializers.ValidationError(
|
||||||
|
"You should use file_num for file keys"
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
int(key.split("_")[1])
|
||||||
|
except ValueError:
|
||||||
|
raise serializers.ValidationError(
|
||||||
|
"You should use file_num for file keys"
|
||||||
|
)
|
||||||
|
len_f += 1
|
||||||
|
if len_f != len(answer):
|
||||||
|
raise serializers.ValidationError(
|
||||||
|
"You should provide the same amount of answers in list as photos"
|
||||||
|
)
|
||||||
|
|
||||||
|
case "multiple_link_description":
|
||||||
|
if type(answer) is not dict:
|
||||||
|
raise serializers.ValidationError("Incorrect type")
|
||||||
|
if any([type(x) is not str for x in answer.keys()]):
|
||||||
|
raise serializers.ValidationError("Incorrect type")
|
||||||
|
if any([type(x) is not str for x in answer.values()]):
|
||||||
|
raise serializers.ValidationError("Incorrect type")
|
||||||
|
|
||||||
|
data["question_id"] = question.id
|
||||||
|
data["deck_id"] = deck.id
|
||||||
|
return data
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
q = QuestionAnswer.objects.get_or_create(
|
||||||
|
deck_id=validated_data["deck_id"], question_id=validated_data["question_id"]
|
||||||
|
)[0]
|
||||||
|
q.answer = validated_data["answer"]
|
||||||
|
q.save()
|
||||||
|
|
||||||
|
s = [
|
||||||
|
key
|
||||||
|
for key, val in validated_data.items()
|
||||||
|
if isinstance(val, TemporaryUploadedFile) and key != "file"
|
||||||
|
]
|
||||||
|
if "file" in validated_data:
|
||||||
|
QuestionAnswerPhoto.objects.create(answer=q, file=validated_data["file"])
|
||||||
|
elif s:
|
||||||
|
s.sort(key=lambda x: int(x.split("_")[1]))
|
||||||
|
for key in s:
|
||||||
|
QuestionAnswerPhoto.objects.create(answer=q, file=validated_data[key])
|
||||||
|
return q
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
RetrievePitchApiView,
|
RetrievePitchApiView,
|
||||||
GetFirstQuestionApiView,
|
GetFirstQuestionApiView,
|
||||||
GetDeckQuestionApiView,
|
GetDeckQuestionApiView,
|
||||||
GetDeckQuestionHintApiView,
|
GetDeckQuestionHintApiView, CreateQuestionAnswerApiView,
|
||||||
)
|
)
|
||||||
|
|
||||||
app_name = "decks"
|
app_name = "decks"
|
||||||
|
@ -15,5 +15,6 @@
|
||||||
path("<int:id>", RetrievePitchApiView.as_view()),
|
path("<int:id>", RetrievePitchApiView.as_view()),
|
||||||
path("question/<int:deck_id>", GetFirstQuestionApiView.as_view()),
|
path("question/<int:deck_id>", GetFirstQuestionApiView.as_view()),
|
||||||
path("question/<int:deck_id>/<int:question_id>", GetDeckQuestionApiView.as_view()),
|
path("question/<int:deck_id>/<int:question_id>", GetDeckQuestionApiView.as_view()),
|
||||||
|
path("question/<int:deck_id>/<int:question_id>/", CreateQuestionAnswerApiView.as_view()),
|
||||||
path("hint/<int:deck_id>/<int:question_id>", GetDeckQuestionHintApiView.as_view()),
|
path("hint/<int:deck_id>/<int:question_id>", GetDeckQuestionHintApiView.as_view()),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
from rest_framework import generics
|
from rest_framework import generics, status
|
||||||
from rest_framework.generics import get_object_or_404
|
from rest_framework.generics import get_object_or_404
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
from rest_framework.parsers import JSONParser, FormParser, MultiPartParser
|
||||||
|
|
||||||
from pitch_deck_generator.decks.api.serializers import (
|
from pitch_deck_generator.decks.api.serializers import (
|
||||||
BasePitchDeckSerializer,
|
BasePitchDeckSerializer,
|
||||||
PitchDeckSerializer,
|
PitchDeckSerializer,
|
||||||
QuestionSerializer, HintSerializer,
|
QuestionSerializer,
|
||||||
|
HintSerializer,
|
||||||
|
AnswerSerializer,
|
||||||
)
|
)
|
||||||
from pitch_deck_generator.decks.models import PitchDeck
|
from pitch_deck_generator.decks.models import PitchDeck, QuestionDeckHint, Question
|
||||||
|
|
||||||
|
|
||||||
class ListDecksApiView(generics.ListCreateAPIView):
|
class ListDecksApiView(generics.ListCreateAPIView):
|
||||||
|
@ -22,22 +25,48 @@ def get_object(self):
|
||||||
return get_object_or_404(PitchDeck, id=self.kwargs["id"])
|
return get_object_or_404(PitchDeck, id=self.kwargs["id"])
|
||||||
|
|
||||||
|
|
||||||
class GetFirstQuestionApiView(generics.GenericAPIView):
|
class GetFirstQuestionApiView(generics.RetrieveAPIView):
|
||||||
serializer_class = QuestionSerializer
|
serializer_class = QuestionSerializer
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get_object(self):
|
||||||
return Response()
|
return Question.objects.get(order=1)
|
||||||
|
|
||||||
|
|
||||||
class GetDeckQuestionApiView(generics.GenericAPIView):
|
class GetDeckQuestionApiView(generics.RetrieveAPIView):
|
||||||
serializer_class = QuestionSerializer
|
serializer_class = QuestionSerializer
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get_object(self):
|
||||||
return Response()
|
return get_object_or_404(Question, id=self.kwargs["question_id"])
|
||||||
|
|
||||||
|
|
||||||
|
class CreateQuestionAnswerApiView(generics.CreateAPIView):
|
||||||
|
serializer_class = AnswerSerializer
|
||||||
|
|
||||||
|
def create(self, request, *args, **kwargs):
|
||||||
|
# main thing starts
|
||||||
|
file_fields = list(request.FILES.keys()) # list to be passed to the serializer
|
||||||
|
serializer = self.get_serializer(data=request.data, file_fields=file_fields)
|
||||||
|
# main thing ends
|
||||||
|
|
||||||
|
serializer.is_valid(raise_exception=True)
|
||||||
|
self.perform_create(serializer)
|
||||||
|
headers = self.get_success_headers(serializer.data)
|
||||||
|
return Response(
|
||||||
|
serializer.data, status=status.HTTP_201_CREATED, headers=headers
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class GetDeckQuestionHintApiView(generics.GenericAPIView):
|
class GetDeckQuestionHintApiView(generics.GenericAPIView):
|
||||||
serializer_class = HintSerializer
|
serializer_class = HintSerializer
|
||||||
|
parser_classes = [JSONParser, FormParser, MultiPartParser]
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
return Response()
|
hint = get_object_or_404(
|
||||||
|
QuestionDeckHint,
|
||||||
|
question_id=self.kwargs["question_id"],
|
||||||
|
deck_id=self.kwargs["deck_id"],
|
||||||
|
)
|
||||||
|
data = hint.hint
|
||||||
|
if data:
|
||||||
|
return Response(data)
|
||||||
|
return Response(status=404)
|
||||||
|
|
|
@ -4,3 +4,9 @@
|
||||||
class DecksConfig(AppConfig):
|
class DecksConfig(AppConfig):
|
||||||
default_auto_field = "django.db.models.BigAutoField"
|
default_auto_field = "django.db.models.BigAutoField"
|
||||||
name = "pitch_deck_generator.decks"
|
name = "pitch_deck_generator.decks"
|
||||||
|
|
||||||
|
def ready(self):
|
||||||
|
try:
|
||||||
|
import pitch_deck_generator.decks.signals # noqa F401
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
# Generated by Django 4.2.4 on 2023-08-26 00:22
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("decks", "0006_alter_question_type"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="question",
|
||||||
|
name="type",
|
||||||
|
field=models.CharField(
|
||||||
|
choices=[
|
||||||
|
("text", "Text"),
|
||||||
|
("number", "Number"),
|
||||||
|
("text_array", "text array"),
|
||||||
|
("range", "Range"),
|
||||||
|
("multiple_range", "multiple range"),
|
||||||
|
("select", "Select"),
|
||||||
|
("link", "Link"),
|
||||||
|
("date", "Date"),
|
||||||
|
("photo", "Photo"),
|
||||||
|
("multiple_photo", "multiple photo"),
|
||||||
|
("photo_description", "photo description"),
|
||||||
|
("multiple_link_description", "multiple link description"),
|
||||||
|
("multiple_photo_description", "multiple photo description"),
|
||||||
|
("multiple_links", "multiple links"),
|
||||||
|
],
|
||||||
|
max_length=26,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="questionanswer",
|
||||||
|
name="deck",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE, to="decks.pitchdeck"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -26,18 +26,24 @@ class Question(models.Model):
|
||||||
class QuestionType(models.TextChoices):
|
class QuestionType(models.TextChoices):
|
||||||
text = "text"
|
text = "text"
|
||||||
number = "number"
|
number = "number"
|
||||||
text_array = "text_array"
|
text_array = "text_array", "text array"
|
||||||
range = "range"
|
range = "range"
|
||||||
multiple_range = "multiple_range"
|
multiple_range = "multiple_range", "multiple range"
|
||||||
select = "select"
|
select = "select"
|
||||||
link = "link"
|
link = "link"
|
||||||
date = "date"
|
date = "date"
|
||||||
photo = "photo"
|
photo = "photo"
|
||||||
multiple_photo = "multiple_photo"
|
multiple_photo = "multiple_photo", "multiple photo"
|
||||||
photo_description = "photo_description"
|
photo_description = "photo_description", "photo description"
|
||||||
multiple_link_description = "multiple link description"
|
multiple_link_description = (
|
||||||
multiple_photo_description = "multiple photo description"
|
"multiple_link_description",
|
||||||
multiple_links = "multiple_links"
|
"multiple link description",
|
||||||
|
)
|
||||||
|
multiple_photo_description = (
|
||||||
|
"multiple_photo_description",
|
||||||
|
"multiple photo description",
|
||||||
|
)
|
||||||
|
multiple_links = "multiple_links", "multiple links"
|
||||||
|
|
||||||
order = models.IntegerField(unique=True)
|
order = models.IntegerField(unique=True)
|
||||||
text = models.CharField(max_length=300)
|
text = models.CharField(max_length=300)
|
||||||
|
@ -65,7 +71,7 @@ class QuestionDeckHint(models.Model):
|
||||||
|
|
||||||
|
|
||||||
class QuestionAnswer(models.Model):
|
class QuestionAnswer(models.Model):
|
||||||
deck = models.FloatField("PitchDeck")
|
deck = models.ForeignKey("PitchDeck", on_delete=models.CASCADE)
|
||||||
question = models.ForeignKey("Question", on_delete=models.CASCADE)
|
question = models.ForeignKey("Question", on_delete=models.CASCADE)
|
||||||
answer = models.JSONField(default=dict)
|
answer = models.JSONField(default=dict)
|
||||||
|
|
||||||
|
|
11
pitch_deck_generator/decks/signals.py
Normal file
11
pitch_deck_generator/decks/signals.py
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
from django.db.models.signals import post_save
|
||||||
|
from django.dispatch import receiver
|
||||||
|
|
||||||
|
from pitch_deck_generator.decks.models import PitchDeck
|
||||||
|
from pitch_deck_generator.decks.tasks import run_pitch_deck_calculation
|
||||||
|
|
||||||
|
|
||||||
|
@receiver(post_save, sender=PitchDeck)
|
||||||
|
def tag_create(sender, instance: PitchDeck, created, **kwargs):
|
||||||
|
if created:
|
||||||
|
run_pitch_deck_calculation.apply_async(kwargs={"pk": instance.pk})
|
|
@ -1,14 +1,52 @@
|
||||||
|
import requests
|
||||||
from celery import shared_task
|
from celery import shared_task
|
||||||
|
|
||||||
from ml.openai_handle import create_name_hint, create_hints
|
from ml.openai_handle import create_name_hint, create_hints
|
||||||
from pitch_deck_generator.decks.models import PitchDeck, Question, QuestionDeckHint
|
from pitch_deck_generator.decks.models import PitchDeck, Question, QuestionDeckHint
|
||||||
|
|
||||||
|
data_types = {
|
||||||
|
"names": ("text", 1),
|
||||||
|
"type": ("select", 13),
|
||||||
|
"category": ("text", 14),
|
||||||
|
"users": ("text", 2),
|
||||||
|
"problems": ("text", 3),
|
||||||
|
"actuality": ("text", 4),
|
||||||
|
"solve": ("text", 5),
|
||||||
|
"works": ("text", 6),
|
||||||
|
"awards": ("text", 7),
|
||||||
|
"market_values": ("multiple_range", 8),
|
||||||
|
"percentage": ("multiple_range", 9),
|
||||||
|
"project_stage": ("select", 10),
|
||||||
|
"money": ("text", 11),
|
||||||
|
"financial_indicators": ("text", 33),
|
||||||
|
"users_metrics": ("multiple_range", 12),
|
||||||
|
"aims": ("text", 15),
|
||||||
|
"money_recieved": ("number", 16),
|
||||||
|
"past_investors": ("text", 17),
|
||||||
|
"how_much_investments": ("range", 18),
|
||||||
|
"finance_model": ("link", 19),
|
||||||
|
"company_value": ("range", 20),
|
||||||
|
"investments_sold": ("text", 21),
|
||||||
|
"time_to_spend": ("date", 22),
|
||||||
|
"achieve": ("text", 23),
|
||||||
|
"future_value": ("range", 24),
|
||||||
|
"your_role": ("photo_description", 25),
|
||||||
|
"your_teammates": ("multiple_photo_description", 26),
|
||||||
|
"competitors": ("text", 27),
|
||||||
|
"competitors_strength": ("text", 28),
|
||||||
|
"competitors_low": ("text", 29),
|
||||||
|
"advantages": ("text", 30),
|
||||||
|
"images": ("multiple_photo", 31),
|
||||||
|
"links": ("multiple_link_description", 32),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@shared_task
|
@shared_task
|
||||||
def run_pitch_deck_calculation(pk: int):
|
def run_pitch_deck_calculation(pk: int):
|
||||||
generate_pitch_deck_name.apply_async(kwargs={"pk": pk})
|
generate_pitch_deck_name.apply_async(kwargs={"pk": pk})
|
||||||
|
generate_known_values.apply_async(kwargs={"pk": pk})
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
generate_pitch_deck_name.apply_async(kwargs={"pk": pk, "num": pk})
|
generate_batch_hints.apply_async(kwargs={"pk": pk, "num": i})
|
||||||
|
|
||||||
|
|
||||||
@shared_task
|
@shared_task
|
||||||
|
@ -23,8 +61,67 @@ def generate_pitch_deck_name(pk: int):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@shared_task
|
||||||
|
def generate_known_values(pk: int):
|
||||||
|
pitch_deck = PitchDeck.objects.get(pk=pk)
|
||||||
|
_, question_id = data_types["category"]
|
||||||
|
QuestionDeckHint.objects.create(
|
||||||
|
question_id=question_id,
|
||||||
|
deck=pitch_deck,
|
||||||
|
hint={
|
||||||
|
"type": "select",
|
||||||
|
"value": [
|
||||||
|
"Business Software",
|
||||||
|
"IndustrialTech",
|
||||||
|
"E-commerce",
|
||||||
|
"Advertising & Marketing",
|
||||||
|
"Hardware",
|
||||||
|
"RetailTech",
|
||||||
|
"ConstructionTech",
|
||||||
|
"Web3",
|
||||||
|
"EdTech",
|
||||||
|
"Business Intelligence",
|
||||||
|
"Cybersecurity",
|
||||||
|
"HrTech",
|
||||||
|
"Telecom & Communication",
|
||||||
|
"Media & Entertainment",
|
||||||
|
"FinTech",
|
||||||
|
"MedTech",
|
||||||
|
"Transport & Logistics",
|
||||||
|
"Gaming",
|
||||||
|
"FoodTech",
|
||||||
|
"AI",
|
||||||
|
"WorkTech",
|
||||||
|
"Consumer Goods & Services",
|
||||||
|
"Aero & SpaceTech",
|
||||||
|
"Legal & RegTech",
|
||||||
|
"Travel",
|
||||||
|
"PropTech",
|
||||||
|
"Energy",
|
||||||
|
"GreenTech",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
req = requests.post(
|
||||||
|
"https://rare-needles-lead.loca.lt/search",
|
||||||
|
json={"body": pitch_deck.description},
|
||||||
|
)
|
||||||
|
data = req.json()
|
||||||
|
_, question_id = data_types["competitors"]
|
||||||
|
QuestionDeckHint.objects.create(
|
||||||
|
question_id=question_id, deck=pitch_deck, hint={"type": "cards", "value": data}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@shared_task
|
@shared_task
|
||||||
def generate_batch_hints(pk: int, num: int):
|
def generate_batch_hints(pk: int, num: int):
|
||||||
pitch_deck = PitchDeck.objects.get(pk=pk)
|
pitch_deck = PitchDeck.objects.get(pk=pk)
|
||||||
data = create_hints(pitch_deck.description, num)
|
data = create_hints(pitch_deck.description, num)
|
||||||
print(data)
|
for el in data:
|
||||||
|
question_type, question_id = data_types[el["type"]]
|
||||||
|
QuestionDeckHint.objects.create(
|
||||||
|
question_id=question_id,
|
||||||
|
deck=pitch_deck,
|
||||||
|
hint={"type": question_type, "value": el["value"]},
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user