mirror of
https://github.com/spbleadersofdigtal/backend.git
synced 2024-11-23 19:53:42 +03:00
update openai, added qr and more
This commit is contained in:
parent
bc33ac8bad
commit
367ef3be53
|
@ -16,10 +16,11 @@
|
|||
"0.0.0.0",
|
||||
"127.0.0.1",
|
||||
"192.168.83.181",
|
||||
"192.168.22.4",
|
||||
"ed68-77-234-219-9.ngrok-free.app",
|
||||
]
|
||||
CORS_ORIGIN_ALLOW_ALL = True
|
||||
CSRF_TRUSTED_ORIGINS = ["https://*.ngrok-free.app"]
|
||||
CSRF_TRUSTED_ORIGINS = ["https://*.ngrok-free.app", "http://192.168.83.181:8000"]
|
||||
|
||||
# WhiteNoise
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import datetime
|
||||
import re
|
||||
from ast import literal_eval
|
||||
|
||||
import openai
|
||||
|
@ -6,6 +7,8 @@
|
|||
|
||||
KEY = settings.OPENAI_KEY
|
||||
|
||||
regex = r"({(\n.+)+\n})"
|
||||
|
||||
description = """🍀 Что такое Pitch-Deck? Pitch-Deck представляет собой презентацию-тизер проекта/компании для
|
||||
инвесторов, партнеров, журналистов и других заинтересованных лиц. Цель презентации - привлечение дополнительного
|
||||
финансирования (инвестиций). Почему это проблема?
|
||||
|
@ -29,7 +32,7 @@
|
|||
создание Pitch-Deck."""
|
||||
|
||||
names_prompt = """
|
||||
По тексту ответь или предположи ответ на вопросы в следющем формате:
|
||||
По тексту ответь или предположи ответ на вопросы в следующем формате:
|
||||
{
|
||||
"names": "Назови 5 имен проекта с данным описанием через запятую"
|
||||
}
|
||||
|
@ -37,7 +40,7 @@
|
|||
|
||||
prompts = [
|
||||
"""
|
||||
По тексту ответь или предположи ответ на вопросы в следющем формате:
|
||||
По тексту ответь или предположи ответ на вопросы в следующем формате:
|
||||
{
|
||||
'users': 'Кто будет пользоваться продуктом',
|
||||
'problems': 'Какие проблемы решает продукт',
|
||||
|
@ -47,24 +50,23 @@
|
|||
}
|
||||
""",
|
||||
"""
|
||||
По тексту ответь или предположи ответ на вопросы в следющем формате:
|
||||
По тексту ответь или предположи ответ на вопросы в следующем формате:
|
||||
{
|
||||
'awards': 'Когда проблема будет решена, какова будет ценность для ваших пользователей',
|
||||
'awards': 'Ценность продукта для пользователей',
|
||||
'money': 'На чем проект зарабатывает? сколько и за что ему платят клиенты',
|
||||
'aims': Напиши 3 цели: на месяц, на полгода и год, формат: {'1': цель на месяц, '2': цель на полгода, '3': цель на год},
|
||||
'investments_sold': 'На что потратить инвестиции под проект',
|
||||
'financial_indicators': 'Напиши финансовые показатели проекта'
|
||||
}
|
||||
""",
|
||||
"""
|
||||
По тексту ответь или предположи ответ на вопросы в следющем формате:
|
||||
{
|
||||
|
||||
'achieve': 'Чего добьется команда после освоения инвестиций',
|
||||
'competitors_strength': 'Сильные стороны конкурентов',
|
||||
'competitors_low': 'Слабые стороны конкурентов',
|
||||
'advantages': 'Какие могут быть преимущества над конкурентами'
|
||||
}
|
||||
"""По тексту ответь или предположи ответ на вопросы в следующем формате: { 'achieve': 'Чего добьется команда после
|
||||
освоения инвестиций', 'competitors_strength': 'Сильные стороны конкурентов', 'competitors_low': 'Слабые стороны
|
||||
конкурентов', 'advantages': 'Какие могут быть преимущества над конкурентами', 'category': "На каком рынке
|
||||
находится этот проект? Выбери из вариантов: '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'" } ,
|
||||
""",
|
||||
]
|
||||
|
||||
|
@ -100,7 +102,12 @@ def create_hints(description: str, stage: int):
|
|||
model="gpt-3.5-turbo",
|
||||
messages=[{"role": "user", "content": description + "\n" + prompts[stage]}],
|
||||
)
|
||||
content = literal_eval(chat_completion.choices[0].message.content)
|
||||
str_content = chat_completion.choices[0].message.content
|
||||
print(str_content)
|
||||
filtered_content = list(re.finditer(regex, str_content, re.MULTILINE))[-1].group()
|
||||
if not len(filtered_content):
|
||||
raise ValueError(f"answer doesnt pass validation, {filtered_content}")
|
||||
content = literal_eval(filtered_content)
|
||||
for assertion_statement in assertions[stage]:
|
||||
assert assertion_statement(content)
|
||||
|
||||
|
|
|
@ -203,6 +203,22 @@ def validate(self, data):
|
|||
raise serializers.ValidationError("Incorrect type")
|
||||
if any([type(x) is not str for x in answer.values()]):
|
||||
raise serializers.ValidationError("Incorrect type")
|
||||
case "multiple_date_description":
|
||||
if type(answer) is not dict:
|
||||
raise serializers.ValidationError("Incorrect type")
|
||||
if not (params["min"] <= len(answer) <= params["max"]):
|
||||
raise serializers.ValidationError(
|
||||
"number of dates is too small or too large"
|
||||
)
|
||||
|
||||
for date in answer.keys():
|
||||
try:
|
||||
parse(date)
|
||||
except ValueError:
|
||||
raise serializers.ValidationError("Incorrect date type")
|
||||
for val in answer.values():
|
||||
if type(val) is not str:
|
||||
raise serializers.ValidationError("Incorrect type")
|
||||
|
||||
data["question_id"] = question.id
|
||||
data["deck_id"] = deck.id
|
||||
|
|
|
@ -32,6 +32,10 @@ class QuestionType(models.TextChoices):
|
|||
select = "select"
|
||||
link = "link"
|
||||
date = "date"
|
||||
multiple_date_description = (
|
||||
"multiple_date_description",
|
||||
"multiple date description",
|
||||
)
|
||||
photo = "photo"
|
||||
multiple_photo = "multiple_photo", "multiple photo"
|
||||
photo_description = "photo_description", "photo description"
|
||||
|
|
|
@ -1,21 +1,40 @@
|
|||
from django.db.models.signals import post_save
|
||||
from django.db.models.signals import post_save, pre_save
|
||||
from django.dispatch import receiver
|
||||
|
||||
from pitch_deck_generator.decks.models import PitchDeck, QuestionAnswer
|
||||
from pitch_deck_generator.decks.tasks import (
|
||||
generate_numeric_values,
|
||||
qenerate_answer_qr,
|
||||
run_pitch_deck_calculation,
|
||||
save_answer_to_deck,
|
||||
)
|
||||
|
||||
|
||||
@receiver(post_save, sender=PitchDeck)
|
||||
def tag_create(sender, instance: PitchDeck, created, **kwargs):
|
||||
def pitch_deck_create(sender, instance: PitchDeck, created, **kwargs):
|
||||
if created:
|
||||
run_pitch_deck_calculation.apply_async(kwargs={"pk": instance.pk})
|
||||
run_pitch_deck_calculation.apply_async(kwargs={"pk": instance.pk}, delay=1)
|
||||
|
||||
|
||||
@receiver(post_save, sender=QuestionAnswer)
|
||||
def question_numeric_run(sender, instance: QuestionAnswer, created, **kwargs):
|
||||
def question_answer_create(sender, instance: QuestionAnswer, created, **kwargs):
|
||||
if created:
|
||||
if instance.question.inner_tag == "category":
|
||||
generate_numeric_values.apply_async(kwargs={"pk": instance.deck.pk})
|
||||
generate_numeric_values.apply_async(
|
||||
kwargs={"pk": instance.deck.pk}, countdown=1
|
||||
)
|
||||
elif instance.question.inner_tag in ["finance_model"]:
|
||||
qenerate_answer_qr.apply_async(kwargs={"pk": instance.pk}, countdown=1)
|
||||
save_answer_to_deck.apply_async(kwargs={"pk": instance.pk}, countdown=5)
|
||||
|
||||
|
||||
@receiver(pre_save, sender=QuestionAnswer)
|
||||
def question_answer_update(sender, instance: QuestionAnswer, created, **kwargs):
|
||||
if instance.id:
|
||||
if instance.question.inner_tag == "category":
|
||||
generate_numeric_values.apply_async(
|
||||
kwargs={"pk": instance.deck.pk}, countdown=1
|
||||
)
|
||||
elif instance.question.inner_tag in ["finance_model"]:
|
||||
qenerate_answer_qr.apply_async(kwargs={"pk": instance.pk}, countdown=1)
|
||||
save_answer_to_deck.apply_async(kwargs={"pk": instance.pk}, countdown=5)
|
||||
|
|
|
@ -1,14 +1,21 @@
|
|||
import tempfile
|
||||
|
||||
import qrcode
|
||||
import requests
|
||||
from celery import shared_task
|
||||
from django.core.files import File
|
||||
|
||||
from ml.openai_handle import create_hints, create_name_hint
|
||||
from pitch_deck_generator.decks.models import (
|
||||
PitchDeck,
|
||||
Question,
|
||||
QuestionAnswer,
|
||||
QuestionAnswerPhoto,
|
||||
QuestionDeckHint,
|
||||
)
|
||||
|
||||
ML_HOST = "https://short-peaches-speak.loca.lt/"
|
||||
|
||||
data_types = {
|
||||
"names": ("text", 1),
|
||||
"type": ("select", 13),
|
||||
|
@ -25,7 +32,7 @@
|
|||
"money": ("text", 11),
|
||||
"financial_indicators": ("text", 33),
|
||||
"users_metrics": ("multiple_range", 12),
|
||||
"aims": ("text", 15),
|
||||
"aims": ("multiple_date_description", 15),
|
||||
"money_recieved": ("number", 16),
|
||||
"past_investors": ("text", 17),
|
||||
"how_much_investments": ("range", 18),
|
||||
|
@ -51,7 +58,7 @@ def run_pitch_deck_calculation(pk: int):
|
|||
generate_pitch_deck_name.apply_async(kwargs={"pk": pk})
|
||||
generate_known_values.apply_async(kwargs={"pk": pk})
|
||||
for i in range(3):
|
||||
generate_batch_hints.apply_async(kwargs={"pk": pk, "num": i})
|
||||
generate_batch_hints.apply_async(kwargs={"pk": pk, "num": i}, delay=1)
|
||||
|
||||
|
||||
@shared_task
|
||||
|
@ -69,47 +76,8 @@ 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",
|
||||
ML_HOST + "search",
|
||||
json={"body": pitch_deck.description},
|
||||
)
|
||||
data = req.json()
|
||||
|
@ -122,14 +90,28 @@ def generate_known_values(pk: int):
|
|||
@shared_task
|
||||
def generate_batch_hints(pk: int, num: int):
|
||||
pitch_deck = PitchDeck.objects.get(pk=pk)
|
||||
data = create_hints(pitch_deck.description, num)
|
||||
try:
|
||||
data = create_hints(pitch_deck.description, num)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
data = create_hints(pitch_deck.description, num)
|
||||
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"]},
|
||||
)
|
||||
if el["type"] == "aims":
|
||||
dates = {}
|
||||
for e in el["value"]:
|
||||
dates[e["date"]] = e["aim"]
|
||||
QuestionDeckHint.objects.create(
|
||||
question_id=question_id,
|
||||
deck=pitch_deck,
|
||||
hint={"type": question_type, "value": dates},
|
||||
)
|
||||
else:
|
||||
QuestionDeckHint.objects.create(
|
||||
question_id=question_id,
|
||||
deck=pitch_deck,
|
||||
hint={"type": question_type, "value": el["value"]},
|
||||
)
|
||||
|
||||
|
||||
@shared_task
|
||||
|
@ -144,7 +126,7 @@ def generate_numeric_values(pk: int):
|
|||
category = q.first().answer
|
||||
type = q2.first().answer
|
||||
req = requests.post(
|
||||
"https://rare-needles-lead.loca.lt/numeric",
|
||||
ML_HOST + "numeric",
|
||||
json={
|
||||
"description": pitch_deck.description,
|
||||
"category": category,
|
||||
|
@ -159,3 +141,28 @@ def generate_numeric_values(pk: int):
|
|||
deck=pitch_deck,
|
||||
hint={"type": question_type, "value": el["value"]},
|
||||
)
|
||||
|
||||
|
||||
@shared_task
|
||||
def save_answer_to_deck(pk: int):
|
||||
qa = QuestionAnswer.objects.get(pk=pk)
|
||||
question = qa.question
|
||||
deck = qa.deck
|
||||
deck.questions[question.inner_tag] = {
|
||||
"answer": qa.answer,
|
||||
"photos": [x.file.url for x in qa.photos.all()],
|
||||
}
|
||||
deck.save()
|
||||
|
||||
|
||||
@shared_task
|
||||
def qenerate_answer_qr(pk: int):
|
||||
qa = QuestionAnswer.objects.get(pk=pk)
|
||||
link = qa.answer
|
||||
img = qrcode.make(link)
|
||||
with tempfile.NamedTemporaryFile() as tmp:
|
||||
img.save(tmp.name)
|
||||
QuestionAnswerPhoto.objects.create(
|
||||
answer=qa,
|
||||
file=File(tmp, name="qr.png"),
|
||||
)
|
||||
|
|
38
poetry.lock
generated
38
poetry.lock
generated
|
@ -2281,6 +2281,18 @@ files = [
|
|||
[package.dependencies]
|
||||
pylint = ">=1.7"
|
||||
|
||||
[[package]]
|
||||
name = "pypng"
|
||||
version = "0.20220715.0"
|
||||
description = "Pure Python library for saving and loading PNG images"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "pypng-0.20220715.0-py3-none-any.whl", hash = "sha256:4a43e969b8f5aaafb2a415536c1a8ec7e341cd6a3f957fd5b5f32a4cfeed902c"},
|
||||
{file = "pypng-0.20220715.0.tar.gz", hash = "sha256:739c433ba96f078315de54c0db975aee537cbc3e1d0ae4ed9aab0ca1e427e2c1"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pytest"
|
||||
version = "7.4.0"
|
||||
|
@ -2455,6 +2467,30 @@ files = [
|
|||
{file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "qrcode"
|
||||
version = "7.4.2"
|
||||
description = "QR Code image generator"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "qrcode-7.4.2-py3-none-any.whl", hash = "sha256:581dca7a029bcb2deef5d01068e39093e80ef00b4a61098a2182eac59d01643a"},
|
||||
{file = "qrcode-7.4.2.tar.gz", hash = "sha256:9dd969454827e127dbd93696b20747239e6d540e082937c90f14ac95b30f5845"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
colorama = {version = "*", markers = "platform_system == \"Windows\""}
|
||||
pypng = "*"
|
||||
typing-extensions = "*"
|
||||
|
||||
[package.extras]
|
||||
all = ["pillow (>=9.1.0)", "pytest", "pytest-cov", "tox", "zest.releaser[recommended]"]
|
||||
dev = ["pytest", "pytest-cov", "tox"]
|
||||
maintainer = ["zest.releaser[recommended]"]
|
||||
pil = ["pillow (>=9.1.0)"]
|
||||
test = ["coverage", "pytest"]
|
||||
|
||||
[[package]]
|
||||
name = "redis"
|
||||
version = "4.6.0"
|
||||
|
@ -3298,4 +3334,4 @@ multidict = ">=4.0"
|
|||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = "^3.11"
|
||||
content-hash = "31ce390d9b50a16455803f012bd6f7eca984fbec0d0e60404edaea07b5523792"
|
||||
content-hash = "e22fcc25641133d1b08cd9bb014e157933077e7a6bd09ce8e4186c844777abf9"
|
||||
|
|
|
@ -49,6 +49,7 @@ pytest-django = "^4.5.2"
|
|||
sentry-sdk = "^1.12.0"
|
||||
openai = "^0.27.9"
|
||||
isort = "5.11.5"
|
||||
qrcode = "^7.4.2"
|
||||
|
||||
|
||||
[build-system]
|
||||
|
|
Loading…
Reference in New Issue
Block a user