Porównaj commity

...

5 Commity

Autor SHA1 Wiadomość Data
rachelhsmith a37a150b36
Merge bd375e783a into dc5639c663 2024-05-01 11:46:53 +03:00
Timothy Elems dc5639c663 Use bash highlighting for code blocks and add note about 'cp' command (#482)
Fixes #390
2024-04-29 15:39:30 +01:00
Rachel Smith bd375e783a empty 2023-12-12 12:52:35 +00:00
Rachel Smith ccd4526a2d add management command to generate gpt blog data 2023-11-20 09:47:17 +00:00
Rachel Smith 12c69b9679 add management command to generate gpt blog data 2023-11-20 09:44:52 +00:00
3 zmienionych plików z 186 dodań i 21 usunięć

Wyświetl plik

@ -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)

Wyświetl plik

@ -5,7 +5,9 @@ agree to abide by the Wagtail [code of conduct](https://github.com/wagtail/wagta
If you do not have write access to the repo, fork, then clone the repo:
git clone git@github.com:your-username/bakerydemo.git
```bash
git clone git@github.com:your-username/bakerydemo.git
```
Set up your machine for [development](https://github.com/wagtail/bakerydemo/blob/master/readme.md).

Wyświetl plik

@ -133,35 +133,41 @@ You can run the Wagtail demo locally without setting up Vagrant or Docker and si
With [PIP](https://github.com/pypa/pip) and [virtualenvwrapper](https://virtualenvwrapper.readthedocs.io/en/latest/)
installed, run:
mkvirtualenv wagtailbakerydemo
python --version
```bash
mkvirtualenv wagtailbakerydemo
python --version
```
Confirm that this is showing a compatible version of Python 3.x. If not, and you have multiple versions of Python installed on your system, you may need to specify the appropriate version when creating the virtualenv:
deactivate
rmvirtualenv wagtailbakerydemo
mkvirtualenv wagtailbakerydemo --python=python3.9
python --version
```bash
deactivate
rmvirtualenv wagtailbakerydemo
mkvirtualenv wagtailbakerydemo --python=python3.9
python --version
```
Now we're ready to set up the bakery demo project itself:
cd ~/dev [or your preferred dev directory]
git clone https://github.com/wagtail/bakerydemo.git
cd bakerydemo
pip install -r requirements/development.txt
```bash
cd ~/dev [or your preferred dev directory]
git clone https://github.com/wagtail/bakerydemo.git
cd bakerydemo
pip install -r requirements/development.txt
```
Next, we'll set up our local environment variables. We use [django-dotenv](https://github.com/jpadilla/django-dotenv)
to help with this. It reads environment variables located in a file name `.env` in the top level directory of the project. The only variable we need to start is `DJANGO_SETTINGS_MODULE`:
cp bakerydemo/settings/local.py.example bakerydemo/settings/local.py
cp .env.example .env
```bash
cp bakerydemo/settings/local.py.example bakerydemo/settings/local.py
cp .env.example .env
# `cp` is used for bash. Windows Command Prompt uses `copy`
```
To set up your database and load initial data, run the following commands:
./manage.py migrate
./manage.py load_initial_data
./manage.py runserver
```bash
./manage.py migrate
./manage.py load_initial_data
./manage.py runserver
```
Log into the admin with the credentials `admin / changeme`.