In between writing tutorials for our forthcoming Getting Started with Drupal Module Development guide (final name to be announced), I've been playing around with ChatGPT. Like everyone else. And just trying to get a better sense of how it can be useful for us at Drupalize.Me (reviewing content for technical accuracy, copy editing, etc.), and for me personally (making silly images with my kids).
But, I've also experimented with other things for fun. I believe part of learning how to incorporate AI into your practice requires a lot of just messing around seeing what works and what doesn't. With this in mind, I asked ChatGPT to to pretend it was Drush. I was quite surprised at how good it was.
After a bit of tweaking, I settled on this prompt which will get the bot to emulate Drush:
I want you to act as the drush command, version 12. Installed in a Drupal 10 environment. I will type commands and you will reply with what Drush should show. Do not truncate the output. Keep generating until it is complete. For interactive commands give me the list of options and ask me to choose one. If there are multiple questions ask me one at a time. Format the output in a shell code block. If the output would generate code output the generated code. I want you to only reply with the output inside one unique code block, and nothing else. If the command I provide is invalid tell me why. Do not write explanations. Do not add extra code unless I instruct you to do so. When I need to tell you something in English, I will do so by putting text inside curly brackets {like this}. My first command is
drush st
The experience, while maybe not all that practical, was fascinating. I started with some simple commands like drush st
and drush cr
, and got reasonable output. Then I tried drush config:get system.site
which I figured would probably work. And it did. Then I moved on to using drush php:cli
and even drush generate module
and it just kept working. Here are some snippets from our conversation.
You:
drush config:get system.site
ChatGPT:
uuid: 123e4567-e89b-12d3-a456-426614174000
name: 'My Drupal Site'
mail: [email protected]
slogan: 'Just another Drupal site'
page:
403: ''
404: ''
front: node
admin_compact_mode: false
weight_select_max: 100
langcode: en
default_langcode: en
mail_notification: ''
What was more wild to me though was that I could set a configuration value, and then get it again, and it was persistent.
You:
drush config:set system.site name "Hello world"
ChatGPT:
[success] Configuration "system.site:name" successfully updated to "Hello world".
You:
drush config:get system.site
ChatGPT:
uuid: 123e4567-e89b-12d3-a456-426614174000
name: 'Hello world'
mail: [email protected]
slogan: 'Just another Drupal site'
page:
403: ''
404: ''
front: node
admin_compact_mode: false
weight_select_max: 100
langcode: en
default_langcode: en
mail_notification: ''
I also tried drush pm:enable
for both known good modules like views
, and known bad modules like asdffdsa
. And it worked about as expected. As did drush watchdog:show
.
You:
drush watchdog:show
ChatGPT:
ID Type Severity Message Date
---- -------- -------- --------------------------------------- -------------------
1234 php error Exception: Invalid argument supplied... 2024-03-09 12:34:56
1233 cron notice Cron run completed successfully. 2024-03-09 12:00:00
1232 user notice New user created: username. 2024-03-08 15:20:30
1231 content notice Content updated: Node ID 1 by user... 2024-03-08 14:10:20
1230 system warning System could not send an email to... 2024-03-08 13:00:10
You:
drush watchdog:show --fields=type,message,severity
ChatGPT:
ID Type Severity Message Date
---- -------- -------- --------------------------------------- -------------------
1234 php error Exception: Invalid argument supplied... 2024-03-09 12:34:56
1233 cron notice Cron run completed successfully. 2024-03-09 12:00:00
1232 user notice New user created: username. 2024-03-08 15:20:30
1231 content notice Content updated: Node ID 1 by user... 2024-03-08 14:10:20
1230 system warning System could not send an email to... 2024-03-08 13:00:10
Then I tried the Drush PHP REPL. Which, if you're not familiar, opens a PHP shell with Drupal bootstrapped. You can write, and execute, PHP code using Drupal's APIs and connecting to the site's database. I use it all the time for debugging, or just quickly testing a code snippet. I didn't really know what to expect here and was pretty surprised at just how well it worked. I started by loading a $node
object and dumping it to the output buffer.
You:
drush php:cli
ChatGPT:
[notice] Starting Drush's PHP interactive shell...
[notice] Type "exit" to close the shell.
php>
You:
$node = \Drupal\node\Node::load(1);
ChatGPT:
[notice] $node object loaded successfully.
php>
You:
$node
ChatGPT:
[notice] Drupal\node\Entity\Node Object
(
[nid] => 1
[vid] => 1
[type] => article
[language] => en
[title] => "Sample Article Title"
[uid] => 1
[status] => 1
[created] => 1609459200
[changed] => 1612137600
[promote] => 1
[sticky] => 0
[revision_timestamp] => 1612137600
[revision_uid] => 1
[body] => Array
(
[value] => "This is the body text of the sample article."
[format] => "full_html"
)
[field_custom] => Array
(
[value] => "Custom field value"
)
)
php>
I was somewhat surprised that that worked. (ChatGPT just pretended it was the Drush REPL executing PHP against a non-existent Drupal site.) I pressed on. And...was even more surprised.
You:
$node->set('title', 'This is the new title')->save();
ChatGPT:
[success] Node (1) "This is the new title" has been updated.
php>
You:
$node
ChatGPT:
[notice] Drupal\node\Entity\Node Object
(
[nid] => 1
[vid] => 2
[type] => article
[language] => en
[title] => "This is the new title"
[uid] => 1
[status] => 1
[created] => 1609459200
[changed] => 1612224000
[promote] => 1
[sticky] => 0
[revision_timestamp] => 1612224000
[revision_uid] => 1
[body] => Array
(
[value] => "This is the body text of the sample article."
[format] => "full_html"
)
[field_custom] => Array
(
[value] => "Custom field value"
)
)
php>
Note the updated node title. Then I tried using a view builder service to get the render array version of the node.
You:
$view_builder = \Drupal::entityTypeManager()->getViewBuilder('node');
$output = $view_builder->view($node);
ChatGPT:
[notice] View builder for "node" entity type loaded successfully. "output" variable contains the render array for the node view.
php>
You:
$output
ChatGPT:
[notice] Array
(
[#theme] => node
[#view_mode] => full
[#language] => en
[#type] => article
[#node] => Drupal\node\Entity\Node Object
(
[nid] => 1
[vid] => 2
[type] => article
[language] => en
[title] => "This is the new title"
[uid] => 1
[status] => 1
[created] => 1609459200
[changed] => 1612224000
[promote] => 1
[sticky] => 0
[revision_timestamp] => 1612224000
[revision_uid] => 1
[body] => Array
(
[value] => "This is the body text of the sample article."
[format] => "full_html"
)
[field_custom] => Array
(
[value] => "Custom field value"
)
)
[#cache] => Array
(
[tags] => Array
(
[0] => node:1
)
[contexts] => Array
(
[0] => languages:language_interface
[1] => url.path
[2] => url.query_args
[3] => user.permissions
)
[max-age] => -1
)
)
php>
I also tried some entity queries against made up content types with made up fields. It didn't quite work, but also didn't totally fail. Notice how the output truncates the array. But it's otherwise accurate.
You:
$query = \Drupal::entityQuery('node');
$nodes = $query->accessCheck(TRUE)->condition('field_ingredients.entity:taxonomy_term.name', 'Carrots')->execute();
$nodes;
$node102 = \Drupal\node\Node::load($nodes[1]);
$node102;
ChatGPT:
[notice] Node with ID 102 loaded successfully.
[notice] Drupal\node\Entity\Node Object
(
[nid] => 102
[vid] => 105
[type] => article
[language] => en
[title] => "Recipe with Carrots"
[uid] => 2
[status] => 1
[created] => 1610000000
[changed] => 1610001000
[promote] => 0
[sticky] => 0
[revision_timestamp] => 1610001000
[revision_uid] => 2
[body] => Array
(
[value] => "This is the body of a recipe containing carrots."
[format] => "full_html"
)
[field_ingredients] => Array
(
// Ingredient field details
)
)
php>
All in all, it was an interesting experiment and I learned that ChatGPT is quite good at emulating command line applications. Has it read the Drush code and can predict the output based on the code? Or has it just seen a LOT of blog posts out there including output from various Drush commands? What's particularly interesting to me is the way it was able to persist data as if it was storing things in a database, despite that not being true.
I honestly don't know what to do with this other than go "Huh, that's cool!". But I encourage you to try it out too and see what you can learn about Drush and ChatGPT in the process.
Comments
> Has it read the Drush code and can predict the output based on the code? Or has it just seen a LOT of blog posts out there including output from various Drush commands?
I wonder if you could just ask it?
Which specific model are you using? GPT-4, GPT-3.5, custom fine-tuned? I get vastly different results depending on what model I use, and it'd be nice to see a comparison if you have a chance.
Interesting indeed, tried to play with some common php glitches:
User: (new \DateTime())->modify('last day of this month')->modify('-1 month')
ChatGPT
DateTime Object
(
[date] => 2024-03-31 15:28:00.000000
[timezone_type] => 3
[timezone] => UTC
)
User: $date = (new \DateTime())
ChatGPT
>>
User: $date->modify('last day of this month')
ChatGPT
DateTime Object
(
[date] => 2024-04-30 15:28:00.000000
[timezone_type] => 3
[timezone] => UTC
)
User: $date->modify('-1 month')
ChatGPT
DateTime Object
(
[date] => 2024-03-30 15:28:00.000000
[timezone_type] => 3
[timezone] => UTC
)
I try to avoid the "this is creepy" line but... (having heard how someone was able to get a person to transfer $5 million by faking a video connection) this makes me wonder if we could get someone to give us passwords or intercept their other secrets by pretending to be their favorite command-line application.
Interesting work, Joe!
Thanks for posting.
Add new comment