kopia lustrzana https://github.com/wagtail/bakerydemo
Porównaj commity
5 Commity
1397be4c41
...
39356b7522
Autor | SHA1 | Data |
---|---|---|
![]() |
39356b7522 | |
![]() |
baff48b7d9 | |
![]() |
bd375e783a | |
![]() |
ccd4526a2d | |
![]() |
12c69b9679 |
|
@ -0,0 +1,157 @@
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
from django.utils import timezone
|
||||||
|
from django.utils.text import slugify
|
||||||
|
from wagtail.rich_text import RichText
|
||||||
|
from django.core.files.base import ContentFile
|
||||||
|
from wagtail.images.models import Image
|
||||||
|
from django.db import IntegrityError
|
||||||
|
|
||||||
|
from bakerydemo.blog.models import BlogIndexPage, BlogPage, BlogPersonRelationship
|
||||||
|
from bakerydemo.base.models import Person
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
import random
|
||||||
|
import datetime
|
||||||
|
from wagtail.models import Collection
|
||||||
|
|
||||||
|
from openai import OpenAI
|
||||||
|
|
||||||
|
FIXTURE_MEDIA_DIR = Path(settings.PROJECT_DIR) / "base/fixtures/media/original_images"
|
||||||
|
client = OpenAI()
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
help = "Creates generated Page data using chatGPT. Useful for demonstrating different use cases."
|
||||||
|
|
||||||
|
def add_arguments(self, parser):
|
||||||
|
parser.add_argument(
|
||||||
|
"--page_count",
|
||||||
|
type=int,
|
||||||
|
help="How many blog pages to create",
|
||||||
|
)
|
||||||
|
|
||||||
|
def make_stream_field_content(self, title, subtitle, collection_name):
|
||||||
|
# get random images for the blog from the generated set
|
||||||
|
image_1 = self.get_random_image(Image, collection_name)
|
||||||
|
image_2 = self.get_random_image(Image, collection_name)
|
||||||
|
# generate rich text for the content
|
||||||
|
prompt = f"""Please give me three paragraphs of content for a blog post called '{title}' with the subtitle '{subtitle}'. They should in JSON of the form {{"paragraph_1": "<p>example</p>", "paragraph_2": "<p>example</p>", "paragraph_3: "<p>example<p>"}} where example is replaced with html content. You may use <p>,<h2>,<h3> and <h4> tags as well as lists. It is the entire blog post so make sure to conclude at the end."""
|
||||||
|
chat_completion = client.chat.completions.create(
|
||||||
|
messages=[
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": prompt,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
model="gpt-4",
|
||||||
|
)
|
||||||
|
streamfield_chat_completion = chat_completion.choices[0].message.content.replace('\n', "")
|
||||||
|
json_streamfield_chat_completion = json.loads(streamfield_chat_completion)
|
||||||
|
|
||||||
|
return [('paragraph_block', RichText(json_streamfield_chat_completion["paragraph_1"])),
|
||||||
|
('image_block', {'image': image_1}),
|
||||||
|
('paragraph_block', RichText(json_streamfield_chat_completion["paragraph_2"])),
|
||||||
|
('image_block', {'image': image_2}),
|
||||||
|
('paragraph_block', RichText(json_streamfield_chat_completion["paragraph_3"])),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def generate_images(self, theme, number_of_images, collection_name):
|
||||||
|
for _ in range(number_of_images):
|
||||||
|
print("Generating image...")
|
||||||
|
prompt = f"an image for blog post about {theme}"
|
||||||
|
response = client.images.generate(
|
||||||
|
model="dall-e-3",
|
||||||
|
prompt=prompt,
|
||||||
|
size="1024x1024",
|
||||||
|
quality="standard",
|
||||||
|
n=1,
|
||||||
|
)
|
||||||
|
# Download the image
|
||||||
|
image_url = response.data[0].url
|
||||||
|
response = requests.get(image_url)
|
||||||
|
# Get or create a collection for the generated images
|
||||||
|
try:
|
||||||
|
collection, created = Collection.objects.get_or_create(name=collection_name)
|
||||||
|
except IntegrityError:
|
||||||
|
root_coll = Collection.get_first_root_node()
|
||||||
|
collection = root_coll.add_child(name=collection_name)
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
# Create a Django ContentFile with the image content
|
||||||
|
image_content = ContentFile(response.content)
|
||||||
|
wagtail_image = Image(title=prompt, collection=collection)
|
||||||
|
wagtail_image.file.save(f"{prompt}.jpg", image_content, save=True)
|
||||||
|
|
||||||
|
def make_title(self, theme):
|
||||||
|
chat_completion = client.chat.completions.create(
|
||||||
|
messages=[
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": f"Create a unique and creative title for a blog post about {theme}. Aim for originality and surprise me with your choice. It should be of the format title: subtitle. Don't include the words title or subtitle in your response",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
model="gpt-4",
|
||||||
|
)
|
||||||
|
content = chat_completion.choices[0].message.content.strip("'").strip('"')
|
||||||
|
title, subtitle = content.split(":", 1)
|
||||||
|
print(f'title: {title}, subtitle: {subtitle}')
|
||||||
|
return title, subtitle
|
||||||
|
|
||||||
|
def make_intro(self, title, subtitle):
|
||||||
|
chat_completion = client.chat.completions.create(
|
||||||
|
messages=[
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": f"Based on the title '{title}' and the subtitle '{subtitle}', create an introduction paragraph for this blog post. Don't repeat the title or the subtitle.",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
model="gpt-4",
|
||||||
|
)
|
||||||
|
content = chat_completion.choices[0].message.content.strip("'")
|
||||||
|
return content
|
||||||
|
|
||||||
|
def get_random_image(self, model, collection_name):
|
||||||
|
return model.objects.filter(collection__name=collection_name).order_by("?").first()
|
||||||
|
|
||||||
|
def get_random_model(self, model):
|
||||||
|
return model.objects.order_by("?").first()
|
||||||
|
|
||||||
|
def get_random_recent_date(self):
|
||||||
|
now = timezone.now()
|
||||||
|
random_day_diff = random.randint(0, 365)
|
||||||
|
random_date = now - datetime.timedelta(days=random_day_diff)
|
||||||
|
return random_date
|
||||||
|
|
||||||
|
def create_pages(self, page_count, theme, collection_name):
|
||||||
|
self.stdout.write("Creating blog pages...")
|
||||||
|
blog_index = BlogIndexPage.objects.live().first()
|
||||||
|
for _ in range(page_count):
|
||||||
|
title, subtitle = self.make_title(theme)
|
||||||
|
new_blog_page = BlogPage(
|
||||||
|
title=title,
|
||||||
|
image=self.get_random_image(Image, collection_name),
|
||||||
|
slug=slugify(title),
|
||||||
|
introduction=self.make_intro(title, subtitle),
|
||||||
|
body=self.make_stream_field_content(title, subtitle, collection_name),
|
||||||
|
subtitle=subtitle,
|
||||||
|
date_published=self.get_random_recent_date(),
|
||||||
|
)
|
||||||
|
blog_index.add_child(instance=new_blog_page)
|
||||||
|
# add an author
|
||||||
|
BlogPersonRelationship.objects.create(page=new_blog_page, person=self.get_random_model(Person))
|
||||||
|
|
||||||
|
def handle(self, **options):
|
||||||
|
theme = input('What should the blog posts be about? ')
|
||||||
|
page_count = int(input('How many blog posts should be created? '))
|
||||||
|
generate_images = input('Do you want to create new images? (y/n): ').lower().strip()
|
||||||
|
if generate_images == 'y':
|
||||||
|
number_of_images = int(input('How many images should be created? '))
|
||||||
|
collection_name = input('What should the collection to keep these images in be called? (Or what is the name of an existing one?) ')
|
||||||
|
else:
|
||||||
|
number_of_images = 0
|
||||||
|
collection_name = input('Which collection do you want to take images from? ')
|
||||||
|
self.generate_images(theme, number_of_images, collection_name)
|
||||||
|
self.create_pages(page_count, theme, collection_name)
|
|
@ -480,7 +480,7 @@ class FormPage(AbstractEmailForm):
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@register_setting
|
@register_setting(icon="cog")
|
||||||
class GenericSettings(ClusterableModel, BaseGenericSetting):
|
class GenericSettings(ClusterableModel, BaseGenericSetting):
|
||||||
twitter_url = models.URLField(verbose_name="Twitter URL", blank=True)
|
twitter_url = models.URLField(verbose_name="Twitter URL", blank=True)
|
||||||
github_url = models.URLField(verbose_name="GitHub URL", blank=True)
|
github_url = models.URLField(verbose_name="GitHub URL", blank=True)
|
||||||
|
@ -498,7 +498,7 @@ class GenericSettings(ClusterableModel, BaseGenericSetting):
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@register_setting
|
@register_setting(icon="site")
|
||||||
class SiteSettings(BaseSiteSetting):
|
class SiteSettings(BaseSiteSetting):
|
||||||
title_suffix = models.CharField(
|
title_suffix = models.CharField(
|
||||||
verbose_name="Title suffix",
|
verbose_name="Title suffix",
|
||||||
|
|
Ładowanie…
Reference in New Issue