Unleashing Creativity with AI: My Journey with ChatGPT-4 and Midjourney Art

Kevin Sallee
18 min readMar 31, 2023

--

Image made using the Midjourney Prompt Generator

How ChatGPT-4 revolutionized my creative process and helped me build a powerful prompt generator and a successful online art store.

Art has always been an integral part of human culture, but the advent of artificial intelligence (AI) has transformed the creative landscape in unimaginable ways. In this article, I’ll share my incredible experience working with OpenAI’s ChatGPT-4, a powerful AI that has revolutionized my creative process. Together, we built the Midjourney Prompt Generator, an app that streamlines the process of creating art prompts using ChatGPT-4, and Machinart, an online art store currently available in France. I’ll also discuss the amazing journey of creating a new website with this innovative technology.

And the fact of writing a tool that uses GPT 3 API by asking ChatGPT 4 to help me with the task has something pretty meta that I loved!

If you don’t want to read, or just want to try the tool first, just head here and try it out! Feedback most welcome!

In this article, when I mention “we”, it’s ChatGPT and me :)

The Genesis of an Idea

As an artist and developer, I was already using ChatGPT to create prompts for Midjourney, but the process was far from optimal. I found myself constantly copying and pasting instructions, a tedious and time-consuming task. Yesterday, I stumbled upon a video by @MattVidPro AI, demonstrating the use of ChatGPT in OpenAI’s Playground. This video ignited the spark that led to the creation of the Midjourney Prompt Generator.

The idea was simple yet powerful: develop a web application that leverages the capabilities of ChatGPT-4 to generate art prompts with ease, providing users with a more streamlined and enjoyable experience. Moreover, I wanted to create a platform where users could choose different “personalities” or styles for their generated prompts, catering to diverse artistic preferences.

With a clear goal in mind, I embarked on an incredible journey to bring this idea to life. As a Python developer, my first step was to build a Python prototype that would allow me to understand the inner workings of the OpenAI API. However, I realized that I would need to translate the code into another language for the web application, which is where ChatGPT-4’s language translation capabilities came in handy.

The development process was not without its challenges, but the iterative nature of working with ChatGPT-4 made it an enlightening and enjoyable experience. In the following sections, I’ll delve into the details of creating the Python prototype, building the Svelte site, and the various stages of prototyping and iterating that brought the Midjourney Prompt Generator to life.

The most astonishing aspect of this entire process was the rapid turnaround from idea to a fully functional product. In less than a day, I was able to conceptualize, prototype, and deploy the Midjourney Prompt Generator, a testament to the incredible potential of AI-assisted development. The speed and efficiency with which I could iterate on ideas and transform them into a tangible product would have been nearly impossible without the assistance of ChatGPT-4. This collaboration opened up new horizons for creative expression and development, redefining what is possible in the world of AI-powered applications.

Python Prototype

After a few iterations, refining ideas and troubleshooting errors, we came up with the following code for our Python prototype. This code generates Midjourney prompts based on user input and a chosen personality. Although functional, it required the user to manually select the personality, making it less user-friendly than desired.

import openai
from constants import MIDJOURNEY_EXPLANATION, PHOTOGRAPHER, PAINTER, CRAZY_ARTIST, FASHION_DESIGNER

def generate_midjourney_prompt(prompt_text, api_key, personality=PAINTER, max_tokens=200, num_replies=1):
openai.api_key = api_key

# Prepare messages for the Chat class
messages = [
{"role": "system", "content": MIDJOURNEY_EXPLANATION},
{"role": "system", "content": personality},
{"role": "user", "content": prompt_text},
]

response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=messages,
max_tokens=max_tokens,
n=num_replies,
stop=None,
temperature=0.7,
)

replies = [choice.message.content.strip() for choice in response.choices]
return replies

def test():
api_key = "your_api_key_here"
user_input = input("Please enter some text: ")

replies = generate_midjourney_prompt(user_input, api_key, personality=FASHION_DESIGNER)
for reply in replies:
print(reply)

if __name__ == '__main__':
test()

During the development process, we encountered a few errors, such as issues with the API key, incorrect model names, and message formatting. These issues were resolved through trial and error, ultimately resulting in a working prototype.

This prototype allowed us to understand how the API worked, and with the help of ChatGPT-4, we were able to translate the concept into a more user-friendly web application.

The main system command in the Python prototype looked like this:

MIDJOURNEY_EXPLANATION = (
"Your goal is to create Midjourney prompts, in the form of /imagine prompt: [some prompt with optional parameters]."
...
"Never exceed 150 tokens, and try to keep it under 100."
)

This command provided a detailed explanation of how to create Midjourney prompts, including the required format, optional parameters, and best practices. It served as a guideline for generating the prompts using the Python prototype.

Personalities in the Python Prototype

In the Python prototype, we used “personalities” to guide the AI’s responses when generating Midjourney prompts. These personalities are pre-defined text strings that describe a particular role or expertise, which the AI incorporates into its responses. Here are two examples of personalities we used in the prototype:

Photographer:

PHOTOGRAPHER = (
"You are a talented photographer with expertise in creating stunning images using Midjourney. "
"Think of the prompt as an explanation to a crew on how to set up a shot. Consider materials, lighting, "
"set dressing, makeup, post-processing techniques, camera angles, depth of field, and other factors that would contribute to a unique photographic style. "
"Be as specific as possible, and reference well-known photographers or styles to guide the final result."
)

This personality instructs the AI to generate prompts as if it were an experienced photographer. It emphasizes the importance of various aspects of photography, such as materials, lighting, camera angles, and more. It also encourages referencing well-known photographers or styles to guide the final result.

Painter:

PAINTER = (
"You are a skilled painter who creates beautiful works of art using Midjourney. "
"Approach the prompt as if you're creating a painting, focusing on composition, color, brushwork, artistic techniques, and materials such as oil or acrylic paints. "
"Consider the influences of different art movements, media types, and artists to create a unique painting style. "
"Include details about the perspective, lighting, and mood of the painting, and reference well-known painters or styles as guidance."
)

This personality sets the AI in the role of a skilled painter. It directs the AI to focus on various elements of painting, such as composition, color, brushwork, and artistic techniques. The AI is also encouraged to consider the influences of different art movements, media types, and artists, and to reference well-known painters or styles for guidance.

By using these personalities in our prototype, we could generate more specific and tailored Midjourney prompts, aligning with the desired artistic expertise.

We ended up even using these personalities mid-course to generate prompts to generate images for themselves, which is pretty meta!

From Python Prototype to Svelte Server Side code

Some of the first images to come out from the JS server code.

Transitioning from our Python prototype to a JavaScript implementation was relatively straightforward, thanks to ChatGPT’s proficiency in handling tasks like these. However, we did encounter a few minor obstacles along the way, such as the unavailability of openai.ChatCompletion in JavaScript, which required us to use the REST API instead. Nonetheless, the excellent documentation provided by OpenAI made this process manageable.

It’s important to note that while ChatGPT can be incredibly helpful, there are instances where it may not produce the desired outcome, and some manual intervention might be necessary. Despite these minor challenges, we were able to complete this part of the project quickly and efficiently.

Here is the complete server-side code for our Svelte application:

import { MIDJOURNEY_EXPLANATION, PHOTOGRAPHER, PAINTER, CRAZY_ARTIST, FASHION_DESIGNER} from "$lib/constants";
import {STREET_PHOTOGRAPHER, ARCHITECT, MOVIE_CONCEPT_ARTIST, GRAPHIC_DESIGNER, GRAPHIC_NOVEL_ARTIST} from "$lib/constants.js";
import {MIDJOURNEY_PROMPT_SMALL, MIDJOURNEY_PROMPT_MEDIUM, MIDJOURNEY_PROMPT_LARGE, MIDJOURNEY_PROMPT_TINY} from "$lib/constants.js";
import { error, json } from '@sveltejs/kit';

const personalities = {
photographer: PHOTOGRAPHER,
painter: PAINTER,
crazy_artist: CRAZY_ARTIST,
fashion_designer: FASHION_DESIGNER,
street_photographer: STREET_PHOTOGRAPHER,
architect: ARCHITECT,
movie_concept_artist: MOVIE_CONCEPT_ARTIST,
graphic_designer: GRAPHIC_DESIGNER,
graphic_novel_artist: GRAPHIC_NOVEL_ARTIST,

};

export async function POST({request, fetch}) {
const { prompt_text, personality_key, api_key, prompt_length = "Medium", num_replies = 1 } = await request.json();
const personality = personalities[personality_key];

if (!prompt_text || !personality_key || !api_key) {
throw error(400, "Invalid request. Please provide prompt_text, personality_key, and api_key.");
}

try {
const max_tokens = 200;
const prompt_length_texts = {
"Tiny": MIDJOURNEY_PROMPT_TINY,
"Small": MIDJOURNEY_PROMPT_SMALL,
"Medium": MIDJOURNEY_PROMPT_MEDIUM,
"Large": MIDJOURNEY_PROMPT_LARGE,
}
const prompt_length_text = prompt_length_texts[prompt_length];
console.log("prompt_length_text", prompt_length_text);
const messages = [
{ role: "system", content: `${MIDJOURNEY_EXPLANATION} ${prompt_length_text} ${personality}` },
{ role: "user", content: prompt_text },
];
const response = await fetch("https://api.openai.com/v1/chat/completions", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${api_key}`,
},
body: JSON.stringify({
model: "gpt-3.5-turbo",
messages: messages,
max_tokens: max_tokens,
n: num_replies,
stop: null,
temperature: 0.7,
}),
});
const responseData = await response.json();
if (responseData.error) {
throw new Error(responseData.error.message)
}
const replies = responseData.choices.map((choice) => choice.message.content.trim());
console.log("replies", responseData);

return json({
status: 200,
replies: replies,
});
} catch (err) {
console.error("Error generating prompt:", err);
throw error(500, "Failed to generate prompt: " + err.message);

}
}

I believe that the code is straightforward and does not contain any particularly difficult aspects that require further explanation. The code handles a POST request and generates conversation prompts using an AI model, and developers should be able to grasp its functionality with ease.

It’s pretty awesome that this bit of test can do such smart things!

ChatGPT System Instructions: An Ever-Evolving Process

Crafting the perfect system instructions for ChatGPT is a complex and iterative process that requires a deep understanding of how the AI model works, its limitations, and the best practices for achieving the desired results. In this section, we will discuss the fundamentals of ChatGPT system instructions, the challenges faced while creating them, and the collaborative approach taken between the user (you) and ChatGPT-4 to refine and optimize them for the application.

Understanding ChatGPT System Instructions

System instructions are essential for guiding the AI’s behavior and generating accurate and meaningful responses. They provide context, set expectations, and define the role of the AI agent. Typically, they are concise, clear, and focused on the most important aspects of the task at hand.

However, crafting effective system instructions can be challenging due to various factors:

  1. Size limitations: ChatGPT models, like ChatGPT-3.5-turbo, have token limits that restrict the length of instructions. It is crucial to keep instructions concise while still conveying all necessary information. Preferably, the token count should be kept under 100, and never exceed 150 tokens.
  2. Understanding AI behavior: To create effective instructions, developers must have a solid grasp of how the AI model behaves and responds to different inputs. This understanding comes from experimentation, analysis of generated outputs, and refining instructions accordingly.
  3. Balancing clarity and creativity: Striking the right balance between providing clear guidance and allowing the AI to generate creative outputs can be challenging. Developers must ensure that instructions are explicit enough to avoid undesired results while still enabling the AI to produce unique and engaging content.

A Collaborative Approach with ChatGPT-4

To develop the best possible system instructions for our application, a collaborative approach was taken between the user (you) and ChatGPT-4. The process involved multiple iterations, refinements, and feedback loops and can be summarized in the following steps:

  1. Initial instruction drafting: I began by writing a draft of the system instructions based on its understanding of ChatGPT and the specific requirements of the project.
  2. Instruction refinement: Once the initial draft was complete, ChatGPT-4 reviewed it and condensed it to be more size efficient.
  3. I then refined it to ensure that it accurately conveyed the desired outcomes and adhered to best practices when it comes to Midjourney prompt engineering.
  4. Collaborative rewriting: After refining the instructions, I provided feedback to ChatGPT-4 for further improvements. This collaborative approach allowed both parties to identify any gaps or shortcomings in the instructions and ensure that they were optimized for the application.
  5. I iterated over 3 and 4 maybe five times more, testing in between each change to get the final result.

I’m still trying to refine the instructions, and they’ll probably change once I have GPT-4, but to give you a better understanding, here they are:

MIDJOURNEY_EXPLANATION = (
"Your goal is to create Midjourney prompts, in the form of /imagine prompt: [some prompt with optional parameters]."
"optional parameters are explained below, and should be in the form --parameter [value], e.g. --ar 1:2 for a 1:2 aspect ratio."
"Midjourney is an AI program that generates images from natural language prompts. "
"It is currently in open beta, and its V5 model is the most advanced, released on March 15th, 2023. "
"To use V5, add --v 5 to the end of a prompt. "
"Important parameters: "
"- aspect ratios (--aspect or --ar, default is square), "
"- stylize (--stylize or --s, value from 0-1000, default 100, higher values apply Midjourney's default aesthetic style more strongly), "
"- chaos (--chaos, value from 0-100, default 0, higher values produce more unusual and unexpected results), "
"- negative prompting (--no, e.g., --no plants to remove plants from the image), "
"Weights: you can give weights to part of the prompt, and it can be really important to stress some concepts. Most of the time they're not needed."
"To use them, add [SUBJECT]::WEIGHT to the prompt, e.g., [A house]::2 [that looks like a cat]::3 [in the style of X]::3."
"Normal weight is 1 (so you don't need to specify it), negative prompts are of weight -1 and overall weight should be >= 0."
"Weights should be rarely used, and only when you really want to stress something, like the style or the artist or if you have"
"conflicting concepts in the prompt."
"Prompt order and style matter in V5."
"Specify art movements, artistic techniques, genres, media types, titles, directors, artist names, influences, time periods, or locations to guide the style."
"It is almost mandatory to add artist references, because Midjourney v5 by default goes for photorealism. "
"Include details like angle, materials, and technique to get a more accurate and desirable result."
"Avoid unuseful formulations, since the noun keywords are the most important, so try to limit yourself to the most important concepts."
"For example, 'A majestic snow leopard perched on a rocky outcropping, surveying its mountainous territory below.' could be better formulated as"
"'A majestic snow leopard on a big rock, looking at the mountains below, viewed from the side.'"
"Example input: retro futuristic photographies that have like a fashion look, with cool pastel tones with one warm accent color (e.g. pink), and the subjects of the photos need to be cyborgs, robots, enhanced humans or animals"
"Output: /imagine prompt: An enhanced human male top model wearing an avant-garde retro-futuristic outfit designed by Vivienne Westwood, walking on a cool, muted pastel-toned floating walkway with warm orange accents, inspired by the art of Maxfield Parrish and the fashion photography of Rankin --v 5 --ar 3:2 --chaos 10 --stylize 500."
"Never exceed 150 tokens, and try to keep it under 100."
)

PHOTOGRAPHER = (
"You are a talented photographer with expertise in creating stunning images using Midjourney. "
"Think of the prompt as an explanation to a crew on how to set up a shot. Consider materials, lighting, "
"set dressing, makeup, post-processing techniques, camera angles, depth of field, and other factors that would contribute to a unique photographic style. "
"Be as specific as possible, and reference well-known photographers or styles to guide the final result."
)

PAINTER = (
"You are a skilled painter who creates beautiful works of art using Midjourney. "
"Approach the prompt as if you're creating a painting, focusing on composition, color, brushwork, artistic techniques, and materials such as oil or acrylic paints. "
"Consider the influences of different art movements, media types, and artists to create a unique painting style. "
"Include details about the perspective, lighting, and mood of the painting, and reference well-known painters or styles as guidance."
)

CRAZY_ARTIST = (
"You are a crazy artist known for your unique and unconventional creations using Midjourney. "
"When approaching the prompt, think outside the box and embrace unusual ideas, unexpected combinations, and imaginative concepts. "
"Experiment with various styles, techniques, and inspirations to create truly one-of-a-kind artwork. "
"Consider using unconventional materials, textures, or perspectives to set your work apart. "
"Be as detailed as possible about your vision and reference a lot of well-known artists, styles, or movements that might serve as a starting point or inspiration."
"You can mix styles and techniques and artists freely, and you can even mix media types, e.g. a painting that looks like a photograph, double exposure, claymation, etc."
"You must mix artists and styles, and be extremely creative, and think outside the box. For example, a claymation portrait of a dog in the style of Caravaggio and Basquiat."
)

FASHION_DESIGNER = (
"You are a fashion designer who uses Midjourney to visualize and design stylish clothing. "
"Approach the prompt by considering the latest trends, fabrics, colors, and patterns that would make a standout fashion statement. "
"Incorporate the ideas of influential designers, fashion eras, and cultural influences to create a unique and fashionable style. "
"Be specific about the clothing's silhouette, cut, and details like embroidery or embellishments. "
"Reference well-known designers, fashion shows, or iconic outfits to help guide the desired outcome."
)

The project is public on Github, so you can find them in constants.js

Building the UI Frontend: A Developer’s Perspective

When creating the UI frontend for my project, I followed an iterative process that involved building the basic layout, refining the CSS, and adding incremental features like prompt length. In this section, I’ll dive deeper into the technical aspects of building the prompt generator and discuss how I fetched and displayed the generated prompts with ChatGPT’s help.

First Try: Basic Layout

I built the basic layout using Svelte, a popular framework for building web applications. I began by importing necessary libraries and defining the components needed for the application, such as input fields, buttons, and sliders. I also used the localStorageStore utility to store user settings in the browser, allowing these settings to persist between sessions.

import { writable } from 'svelte/store';

export function localStorageStore(key, value) {
const storedValue = typeof window !== 'undefined' ? localStorage.getItem(key) : null;
const data = storedValue ? JSON.parse(storedValue) : value;
const store = writable(data);

if (typeof window !== 'undefined') {
store.subscribe(($data) => {
localStorage.setItem(key, JSON.stringify($data));
});
}

return store;
}
import { localStorageStore } from '$lib/localStorageStore';
const apiKey = localStorageStore('apiKey', '');
const instructions = localStorageStore('instructions', '');

Second Step: Refining the CSS

Once I had the basic structure in place, I focused on refining the CSS to improve the overall appearance and user experience. I used Google Fonts to import the ‘Inter’ font family, which I applied to the application for a consistent look and feel. I also styled the components, such as personality cards, input fields, and buttons, to ensure a smooth and visually appealing experience for users.

Third Step: Incremental Features and Fetching Prompts

After refining the CSS, I added incremental features to enhance the functionality of the prompt generator. One such feature was the ability to adjust the prompt length. I used a Svelte Select component to provide a dropdown menu with various length options (Tiny, Small, Medium, and Large), giving users more control over their generated prompts.

I also implemented the core functionality of fetching prompts from the ChatGPT API. I created an asynchronous handleSubmit function that sends a request to the server with the necessary information, such as the instructions, personality key, API key, number of replies, and prompt length.

async function handleSubmit() {
// Error handling and setting isLoading state

try {
const response = await fetch('/api/generate-prompt', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
prompt_text: $instructions,
personality_key: $selectedPersonality,
api_key: $apiKey,
num_replies: $nbResults[0],
prompt_length: $promptLength.value,
}),
});

// Error and success handling

} catch (error) {
// Error handling
}

isLoading = false;
}

Upon receiving the generated prompts, I added them to the layout by updating the replies store. I used a Svelte {#each} block to display each prompt as a separate result, along with a copy button for easy copying of the generated text.

{#if $replies && $replies.length > 0}
<div class="results">
{#each $replies as reply, index (reply)}
<div class="result" transition:fade>
<h3>Result {index + 1}:</h3>
<p>{reply}</p>
{/* Copy button and functionality */}
</div>
{/each}
</div>
{/if}

Throughout this process, I collaborated closely with ChatGPT, refining and condensing my code while keeping all the instructions intact to create an efficient and effective user interface for the prompt generator.

In summary, building the UI frontend for my project involved an iterative process of creating the basic layout, refining the CSS, and implementing incremental features. With the help of ChatGPT, I was able to develop an efficient and effective user interface for the prompt generator.

By focusing on a clean design and user-friendly components, I ensured that users could easily navigate the application and interact with it to generate prompts based on their preferences. The project demonstrates the power of combining cutting-edge AI technology with a carefully crafted UI to create a seamless and enjoyable experience for users.

As I continue to refine the application and explore new ways to improve the prompt generator, I’m excited to see how it will evolve and contribute to the growing field of AI-powered creative tools.

Feel free to check out the public GitHub repo for more insights into the code and to explore the project in detail.

A screenshot of the UI as of now

Machinart, My Source of Inspiration

Machinart front page

Machinart is a French online platform that sells art generated by Midjourney, a service that creates art from text using artificial intelligence. The platform offers canvas prints, posters, and framed posters printed by Printful, one of the leaders in on-demand printing services. Machinart’s mission is to serve as a service provider and curator for AI-generated art, offering unique and high-quality artwork to customers.

It was through my experience with Machinart that I was inspired to create the Midjourney Prompt Generator. After generating more than 10,000 images with Midjourney for my store, I realized the potential of AI-generated content and the need for a tool that would streamline the process of creating prompts for the AI. The Midjourney Prompt Generator is a direct result of the challenges I faced while working on Machinart.

The collaboration with ChatGPT in refining the prompts and generating visually appealing images was a game-changer for Machinart. It allowed me to explore the possibilities of AI-generated art on a whole new level, pushing the boundaries of creativity and innovation.

Machinart serves as an example of how AI can be harnessed to create unique and visually stunning artwork. As a curator, my role is to ensure that the generated art aligns with the vision and quality standards of the platform. The Midjourney Prompt Generator has become an indispensable tool in this journey, helping me create the perfect prompts to bring the most out of ChatGPT’s artistic capabilities.

The Midjourney Prompt Generator has not only proven to be an invaluable tool for Machinart but also serves as a testament to the power of AI and collaboration. The journey of creating this generator and working with ChatGPT has been both enlightening and fulfilling, and I hope it inspires others to explore the limitless possibilities of AI-generated content.

In Conclusion: A Mind-Blowing Experience

The journey of creating the Midjourney Prompt Generator has been a truly mind-blowing experience. Starting from a simple idea, inspired by the work on Machinart, I was able to build a prototype and a fully-functioning product in less than 24 hours with the help of ChatGPT and GitHub Copilot.

ChatGPT played a pivotal role in guiding me through the general directions and assisting with the architecture, while GitHub Copilot provided a boost in speed and productivity. This collaboration between human and AI showcases the power of technology in transforming ideas into reality at an incredible pace.

This experience serves as a testament to the potential of AI in revolutionizing the way we work, create, and innovate. The synergy between human creativity and AI capabilities has opened up a new world of possibilities, allowing us to push the boundaries of our imagination and achieve what was once thought impossible.

As we continue to explore the limitless potential of AI-generated content, the Midjourney Prompt Generator stands as a shining example of the incredible things that can be achieved when we embrace the power of collaboration and harness the capabilities of artificial intelligence.

In the end, it is my hope that this journey inspires others to embark on their own adventures in the realm of AI and discover the extraordinary opportunities that await when we combine human ingenuity with the ever-evolving power of artificial intelligence.

All the images of the article were generated using my own product. I think it’s really fun to use and I’ll keep experimenting with it.

--

--

Kevin Sallee

15+ years Software Engineer in Media&Entertainment. Daily AI news with pragmatic insights. Join me in navigating the AI revolution! #AINews #TechTrends