ChatGPT Plugin - A basic example using SWI-Prolog on the backend

If you don’t know what ChatGPT is you can sign up for free at https://chat.openai.com/. Signing up does require a valid phone number that can receive SMS messages for confirmation.

The introductory documentation for ChatGPT plugins can be found at https://platform.openai.com/docs/plugins/introduction

For a plugin to work it needs to communicate between two endpoints, with one endpoint being ChatGPT. To create a programming language independent API, OpenAPI is used. OpenAPI uses a specification file.

ChatGPT uses the OpenAPI specification file to understand how to create HTTP(S) request to send to the plugin and what expected responses exist.

The plugin is created using any programming language that can run an HTTP(S) server and communicate using REST.

Three additional files needed to create a ChatGPT plugin are

  • A logo file for displaying an image along with a textual name of the plugin.
  • A manifest file that contains some basic fields including the location the OpenAPI specification for the plugin.
  • The code to run the HTTP(S) server.

The basic file layout of many plugins is

C:.
|   logo.png
|   main.py
|   openapi.yaml
\---.well-known
        ai-plugin.json

This example will use SWI-Prolog and have just one POST command to receive SWI-Prolog code which it will compile and then return the results.

The manifest file, named ai-plugin.json, is typical for most introductory plugins.

For the ChatGPT plugin - SWI-Prolog REPL this is ai-plugin.json

{
  "schema_version": "v1",
  "name_for_human": "SWI-Prolog REPL",
  "name_for_model": "SWI_Prolog_REPL",
  "description_for_human": "Compile SWI-Prolog code and return results, success or errors.",
  "description_for_model": "Compile SWI-Prolog code and return results, success or errors.",
  "auth": {
    "type": "none"
  },
  "api": {
    "type": "openapi",
    "url": "http://localhost:5003/openapi.yaml",
    "is_user_authenticated": false
  },
  "logo_url": "http://localhost:5003/logo.png",
  "contact_email": "support@example.com",
  "legal_info_url": "https://example.com/legal"
}

The next file is the OpenAPI spec. It is often easier to create by just giving ChatGPT a basic description and it will often create one with little to no errors, sometimes a few changes are needed to be validated by OpenAI when installing the ChatGPT plugin.


Prompt
ChatGPT May 24 Version

Create an OpenAPI specification that will post SWI-Prolog code and return the results of compiling the code, either success or the errors.

Completion

Sure! Here’s an example of an OpenAPI specification (using the OpenAPI 3.0 syntax) for an endpoint that accepts SWI-Prolog code as input and returns the results of compiling the code, including success or any errors encountered.

openapi: 3.0.3
info:
  title: SWI-Prolog Compiler API
  version: 1.0.0
servers:
  - url: http://api.example.com/prolog
paths:
  /compile:
    post:
      summary: Compile SWI-Prolog code
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                code:
                  type: string
                  description: SWI-Prolog code to compile
              required:
                - code
      responses:
        '200':
          description: Compilation result
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    description: Indicates whether the compilation was successful
                  errors:
                    type: array
                    items:
                      type: string
                    description: Compilation errors (if any)
        '400':
          description: Invalid request
        '500':
          description: Internal server error

This OpenAPI specification defines a single endpoint, /compile, which accepts a POST request with a JSON payload containing the SWI-Prolog code to be compiled. The response will include a success field indicating whether the compilation was successful and an errors field containing any compilation errors encountered.

You can use this specification to generate API documentation, client SDKs, or server stubs using tools like Swagger UI or OpenAPI Generator.


The ChatGPT generated OpenAPI specification was close to the working version, here is the working version.

openapi: 3.1.0
info:
  title: SWI-Prolog Compiler API
  description: A plugin to compile SWI-Prolog and return success or errors.
  version: 0.0.0.1
servers:
  - url: http://localhost:5003
paths:
  /compile:
    post:
      operationId: compileCode
      summary: Compile SWI-Prolog code
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                code:
                  type: string
                  description: SWI-Prolog code to compile
              required:
                - code
      responses:
        '200':
          description: Compilation result
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    description: Indicates whether the compilation was successful
                  errors:
                    type: array
                    items:
                      type: string
                    description: Compilation errors (if any)
        '400':
          description: Invalid request
        '500':
          description: Internal server error

The logo is created as PNG file and uses the SWI-Prolog owl which can be found in most installation directories of SWI-Prolog.

For this example SWI-Prolog MQI will be used so that the HTTP server with CORS can be created using Python. Tired to create the HTTP server with CORS for this using SWI-Prolog but could never get it to work. Seems HTTP servers with CORS created with Python just work as expected with ChatGPT plugins.

To use SWI-Prolog MQI with this code ran

pip install swiplserver

which created files in C:\Users\Eric\AppData\Local\Programs\Python

While I did not try to create a single ChatGPT prompt that would create the Python code using the OpenAPI specification and some other constraints such as using CORS, adding routes for the three static files and including SWI-Prolog MQI much of the Python code was created and refined using ChatGPT prompts.

As this example is a proof of concept rather than production quality code there are many places that optimizations can be made.

For the HTTP server with CORS created with Python to work, some additional Prolog files needed to be created, since the Prolog code is being passed as a string and the quickest way to compile it was to place the Prolog code from ChatGPT into a file, then compile it. Also when using load_files/2 the error messages need to be captured from message_hook/3 which was better hidden in a Prolog file, thus compile.pl was created to simplify the Python code.

Note: catch_messages/2 is from https://github.com/SWI-Prolog/packages-http/blob/010d4a0d0eb76b8f22f42ce4db7d75f7b555a8d1/test_proxy.pl#L672-L699. Thanks Jan W., I knew the overall idea but once I saw this code decided not to roll my own.

FIle: compile.pl

:- module(compile,[
        compile/1
    ]).

% ----------------------------------------------------------------------------

:- meta_predicate
    catch_messages(0, -).

catch_messages(Goal, Messages) :-
    nb_setval(messages, []),
    thread_self(Me),
    setup_call_cleanup(assert((user:message_hook(Term, Kind, Lines) :-
                                    catch_message(Me, message(Term,Kind,Lines))),
                            Ref),
                    once(Goal),
                    collect_messages(Messages, Ref)).

catch_message(Me, message(Term,Kind,Lines)) :-
    Kind \= silent,
    thread_self(Me),
    !,    
    nb_getval(messages, L0),
    message_to_string(Term, String),
    (   source_location(File, Line)
    ->  true
    ;   File = "",
        Line = 0
    ),
    nb_linkval(messages, [message(Term,Kind,Lines,File,Line,String)|L0]).

collect_messages(Messages, Ref) :-
    erase(Ref),
    nb_getval(messages, L),
    nb_delete(messages),
    reverse(L, Messages).

% ----------------------------------------------------------------------------

compile(Errors) :-
    catch_messages(
        load_files(['code.pl'],[]),
        Messages
    ),
    maplist(format_message,Messages,Errors).

format_message(message(_Term,_Kind,_Lines,_File,Line,Error),error(Line,Error)).

Lastly the Python HTTP server with CORS.
FIle: main.py

from flask import Flask, jsonify, request, send_from_directory
from flask_cors import CORS
from werkzeug.exceptions import BadRequest, InternalServerError
from swiplserver import PrologMQI, PrologThread
import json

app = Flask(__name__)
CORS(app)

# Serve static files from the root directory
@app.route('/logo.png', methods=['GET'])
def serve_files():
    return send_from_directory('.', 'logo.png')

@app.route('/.well-known/ai-plugin.json', methods=['GET'])
def serve_ai_plugin():
    return send_from_directory('.well-known', 'ai-plugin.json')

@app.route('/openapi.yaml', methods=['GET'])
def serve_openapi():
    return send_from_directory('.', 'openapi.yaml')

@app.route('/compile', methods=['POST'])
def compile_code():
    try:
        json_reqeust = request.get_json(force=True)
        print("Request:", request.method, request.path, json_reqeust)  # Print the request to the console
        
        # Extract the 'code' from the request JSON
        code = json_reqeust['code']
        print("Code: ", code)

        # Save code to file so it can be compiled.
        with open("code.pl", "w") as file:
            # Write the string to the file
            file.write(code)
        
        with PrologMQI() as mqi:
            with mqi.create_thread() as prolog_thread:  
                result = prolog_thread.query('[compile]')        
                print(result)        
                errors = prolog_thread.query('compile:compile(Errors)')             
                print(errors)
                error_message = []
                try:
                    error_message = errors[0]['Errors'][0]['args'][1]
                except (IndexError, KeyError):
                    pass
   
        # Placeholder response for demonstration purposes
        response = {
            'success': True,
            'Errors': error_message
        }
        
        return jsonify(response), 200
    
    except BadRequest:
        return jsonify({'error': 'Invalid request'}), 400
    
    except Exception as e:
        return jsonify({'error': str(e)}), 500

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5003)

How to install the ChatGPT plugin - SWI-Prolog REPL.

First the HTTP server needs to be running.

From a Windows command prompt

  1. Change directory to directory with main.py
  2. python main.py
C:\Users\Groot\SWI-Prolog REPL>python main.py
 * Serving Flask app 'main'
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on all addresses (0.0.0.0)
 * Running on http://127.0.0.1:5003
 * Running on http://192.168.1.143:5003
Press CTRL+C to quit

Navigate to https://chat.openai.com/
Note: Many developers prefer to use Chrome at this point as it is the one OpenAI supports and fixes the bugs fastest.

Disable caching for the browser.

image

Click dropdown arrow
image

Click Plugins


Click Plugin store

In lower right click Develop your own plugin

image

For Domain enter: localhost:5003 (change port number to one server is using)
Click Find manifest file

image

You can click the dropdowns to see the manifest file and OpenAPI specification file found, this is handy to make sure the correct files are accessed.

Click: Install localhost plugin

One nice debugging tool for ChatGPT is Open plugin devtools. This can be enabled through the ChatGPT settings.

image

Notice that in the right of the ChatGPT page the Plugin devtools panel opened.

image

The only thing new here is Prompt for ChatGPT which is TypeScript

// Compile SWI-Prolog code and return results, success or errors.
namespace SWI_Prolog_REPL {

// Compile SWI-Prolog code
type compileCode = (_: {
// SWI-Prolog code to compile
code: string,
}) => any;

} // namespace SWI_Prolog_REPL

My take is that this is the API used by the ChatGPT web pages to communicate with the plugin. As can be seen it is very simple.


To use the plugin make sure it is activated, has a check mark in a green circle. It also helps during development if only one plugin at a time is activated.
image

The first prompt I run is to see if ChatGPT understands what the plugin does.


Prompt
ChatGPT May 24 Version

What can SWI-Prolog REPL plugin do?

Completion

The SWI-Prolog REPL (Read-Eval-Print Loop) plugin is a tool that allows you to compile and run SWI-Prolog code. Prolog is a logic programming language associated with artificial intelligence and computational linguistics.

Here’s what you can do with the SWI-Prolog REPL plugin:

  1. Compile and Run Prolog Code: You can write Prolog code and have it compiled and run within the chat. This is useful for testing small snippets of code or for demonstrating how Prolog works.

  2. Debug Prolog Code: If there are errors in your Prolog code, the REPL will provide error messages that can help you debug your code.

  3. Interactive Programming: The REPL nature of the plugin allows for interactive programming. You can run a piece of code, see the output, then modify and rerun the code based on the output.

  4. Teaching and Learning: The plugin can be a useful tool for teaching and learning Prolog. You can demonstrate Prolog concepts and students can practice writing Prolog code.

Remember that the plugin is a tool for running Prolog code and does not provide any Prolog-specific features beyond what is available in the SWI-Prolog system. It also does not provide features like code completion or syntax highlighting that you might find in a dedicated Prolog development environment.



The next prompt is to create some example prompts to try with the plugin, sometimes ChatGPT comes up with some interesting prompts.

Prompt
ChatGPT May 24 Version

Create some simple prompts to test out SWI-Prolog REPL plugin. Do not create API calls but prompts a real person would create.

Completion

Sure, here are some prompts that a real person might create to test out the SWI-Prolog REPL plugin:

  1. Fact and Rule Creation: “Can you write a Prolog program that defines a parent-child relationship? Let’s say that John is the parent of Jim, and Jim is the parent of Tim. Then, define a rule to determine if someone is a grandparent.”

  2. List Manipulation: “Can you write a Prolog program that defines a predicate to find the last element of a list?”

  3. Recursion: “Can you write a Prolog program that uses recursion to calculate the factorial of a number?”

  4. Path Finding: “Can you write a Prolog program that defines a simple graph with nodes and edges, and then finds a path between two nodes?”

  5. Pattern Matching: “Can you write a Prolog program that uses pattern matching to split a list into its head and tail?”

  6. Sorting: “Can you write a Prolog program that sorts a list of numbers in ascending order?”

  7. Predicate Logic: “Can you write a Prolog program that defines a predicate to determine if a number is even?”

Remember, these are prompts for testing the SWI-Prolog REPL plugin. The actual Prolog code would be written in response to these prompts.



Now to test the ChatGPT plugin - SWI-Prolog REPL.

Prompt
ChatGPT May 24 Version

Can you write a Prolog program that defines a parent-child relationship? Let’s say that John is the parent of Jim, and Jim is the parent of Tim. Then, define a rule to determine if someone is a grandparent.

Completion

image

image


Notes: The first time the code passed to the SWI-Prolog plugin is not formatted correctly and returns an error. Once ChatGPT sees the error it corrects the formatting of the code and sends it to the plugin again. The second time the code does compile clean.



Next we give some invalid code.

Prompt
ChatGPT May 24 Version

Create some Prolog code with a syntax error to test the SWI-Prolog REPL plugin.

Completion


Notes: The first time ChatGPT tried to create Prolog code with a syntax error it failed but it recognized that the error was not a syntax error and tried again, this time getting it correct. The use of Used unknown plugin is common among many plugins, still have not seen a minimal working example that can reproduce it so that OpenAI can fix the problem.



Here ia a partial listing of the Python HTTP server console.

127.0.0.1 - - [10/Jun/2023 15:35:42] "OPTIONS /logo.png HTTP/1.1" 200 -
127.0.0.1 - - [10/Jun/2023 15:35:42] "GET /logo.png HTTP/1.1" 200 -
127.0.0.1 - - [10/Jun/2023 15:40:02] "OPTIONS /compile HTTP/1.1" 200 -
Request: POST /compile {'code': 'parent(john jim).\nparent(jim, tim).\ngrandparent(X, Z) :- parent(X, Y), parent(Y, Z).'}
Code:  parent(john jim).
parent(jim, tim).
grandparent(X, Z) :- parent(X, Y), parent(Y, Z).
True
[{'Errors': [{'args': [1, 'c:/users/eric/projects/chatgpt plugin/python based/eric/swi-prolog repl/code.pl:1:12: Syntax error: Operator expected'], 'functor': 'error'}]}]
127.0.0.1 - - [10/Jun/2023 15:40:03] "POST /compile HTTP/1.1" 200 -
127.0.0.1 - - [10/Jun/2023 15:40:20] "OPTIONS /logo.png HTTP/1.1" 200 -
127.0.0.1 - - [10/Jun/2023 15:40:20] "GET /logo.png HTTP/1.1" 200 -
127.0.0.1 - - [10/Jun/2023 15:40:22] "GET /logo.png HTTP/1.1" 200 -
127.0.0.1 - - [10/Jun/2023 15:40:49] "OPTIONS /compile HTTP/1.1" 200 -
Request: POST /compile {'code': 'This is not valid Prolog code.'}
Code:  This is not valid Prolog code.
True
[{'Errors': [{'args': [1, 'c:/users/eric/projects/chatgpt plugin/python based/eric/swi-prolog repl/code.pl:1:12: Syntax error: Operator expected'], 'functor': 'error'}]}]
127.0.0.1 - - [10/Jun/2023 15:40:50] "POST /compile HTTP/1.1" 200 -
127.0.0.1 - - [10/Jun/2023 15:41:37] "OPTIONS /compile HTTP/1.1" 200 -
Request: POST /compile {'code': 'father(john, jim).\nfather(john, ann).\nbrother(X, Y) :- father(Z, X), father(Z, Y), X \\= Y.'}
Code:  father(john, jim).
father(john, ann).
brother(X, Y) :- father(Z, X), father(Z, Y), X \= Y.
True
[{'Errors': []}]
127.0.0.1 - - [10/Jun/2023 15:41:38] "POST /compile HTTP/1.1" 200 -
127.0.0.1 - - [10/Jun/2023 15:41:51] "OPTIONS /compile HTTP/1.1" 200 -
Request: POST /compile {'code': 'father(john, jim)\nfather(john, ann).\nbrother(X, Y) :- father(Z, X), father(Z, Y), X \\= Y.'}
Code:  father(john, jim)
father(john, ann).
brother(X, Y) :- father(Z, X), father(Z, Y), X \= Y.
True
[{'Errors': [{'args': [1, 'c:/users/eric/projects/chatgpt plugin/python based/eric/swi-prolog repl/code.pl:1:18: Syntax error: Operator expected'], 'functor': 'error'}]}]
127.0.0.1 - - [10/Jun/2023 15:41:52] "POST /compile HTTP/1.1" 200 -


So there is much work to be done with this ChatGPT plugin - SWI-Prolog REPL but it does show that as a proof of concept it can be done.

1 Like

Since the original plugin was not always passing the Prolog code from ChatGPT to the ChatGPT Plugin HTTP server in format expected, to fix first tied passing the Prolog code as plain/text which when used with POST would always generate a Prompt for ChatGPT with

// Plugin to pass OpenAPI reqeust as text/plain.
namespace String_arugment_test {

// pass text
type passText = () => any;

} // namespace String_arugment_test

the TypeScript API created from the OpenAPI specification would never recognize the text/plain as an argument.

In checking every plugin OpenAPI specification listed here, they all use application/json for POST.

File updates and other details (click triangle to expand)

Manifest: .well-known\ai-plugin.json

{
  "schema_version": "v1",
  "name_for_human": "SWI-Prolog REPL",
  "name_for_model": "SWI_Prolog_REPL",
  "description_for_human": "Compile SWI-Prolog code and return results, success or errors.",
  "description_for_model": "Validate Prolog code generated by ChatGPT uisng SWI-Prolog and return results, success or errors. Transform Prolog code in prompt to application/json before sending to plugin.",
  "auth": {
    "type": "none"
  },
  "api": {
    "type": "openapi",
    "url": "http://localhost:5003/openapi.yaml",
    "is_user_authenticated": false
  },
  "logo_url": "http://localhost:5003/logo.png",
  "contact_email": "support@example.com",
  "legal_info_url": "https://example.com/legal"
}

One of the major changes was

“description_for_model”: “Validate Prolog code generated by ChatGPT using SWI-Prolog and return results, success or errors. Transform Prolog code in prompt to application/json before sending to plugin.”

Thanks duncansmothers (ref)

OpenAPI specification: openapi.yaml

openapi: 3.1.0
info:
  title: SWI-Prolog Compiler API
  description: A plugin to compile SWI-Prolog and return success or errors.
  version: 0.0.0.1
servers:
  - url: http://localhost:5003
paths:
  /compile:
    post:
      operationId: compileCode
      summary: compile
      requestBody:
        description: Compile SWI-Prolog code
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                code:
                  type: string
                  description: SWI-Prolog code to compile
      responses:
        '200':
          description: Compilation result
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    description: Indicates whether the compilation was successful
                  errors:
                    type: array
                    items:
                      type: string
                    description: Compilation errors (if any)
        '400':
          description: Invalid request
        '500':
          description: Internal server error

Python: main.py

from flask import Flask, jsonify, request, send_from_directory
from flask_cors import CORS
from werkzeug.exceptions import BadRequest, InternalServerError
from swiplserver import PrologMQI, PrologThread
import json

app = Flask(__name__)
CORS(app)

# Serve static files from the root directory
@app.route('/logo.png', methods=['GET'])
def serve_files():
    return send_from_directory('.', 'logo.png')

@app.route('/.well-known/ai-plugin.json', methods=['GET'])
def serve_ai_plugin():
    return send_from_directory('.well-known', 'ai-plugin.json')

@app.route('/openapi.yaml', methods=['GET'])
def serve_openapi():
    return send_from_directory('.', 'openapi.yaml')

@app.route('/compile', methods=['POST'])
def compile_code():
    try:
        data = request.get_json(force=True)
        
        # Extract the 'code' from the request JSON
        code = data['code']

        print("Request:", request.method, request.path, data)  # Print the request to the console
        print("Code: ", code)

        # Save code to file so it can be compiled.
        with open("code.pl", "w") as file:
            # Write the string to the file
            file.write(code)
        
        with PrologMQI() as mqi:
            with mqi.create_thread() as prolog_thread:  
                result = prolog_thread.query('[compile]')        
                print(result)        
                errors = prolog_thread.query('compile:compile(Errors)')             
                print(errors)
                error_message = []
                try:
                    error_message = errors[0]['Errors'][0]['args'][1]
                except (IndexError, KeyError):
                    pass
   
        response = {
            'success': True,
            'Errors': error_message
        }
        
        return jsonify(response), 200
    
    except BadRequest:
        return jsonify({'error': 'Invalid request'}), 400
    
    except Exception as e:
        return jsonify({'error': str(e)}), 500

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5003)

The remaining files stayed the same.

Example of HTTP server console.

C:\Users\Groot\SWI-Prolog REPL>python main.py
 * Serving Flask app 'main'
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on all addresses (0.0.0.0)
 * Running on http://127.0.0.1:5003
 * Running on http://192.168.1.143:5003
Press CTRL+C to quit
127.0.0.1 - - [13/Jun/2023 07:46:16] "OPTIONS /.well-known/ai-plugin.json HTTP/1.1" 200 -
127.0.0.1 - - [13/Jun/2023 07:46:17] "GET /.well-known/ai-plugin.json HTTP/1.1" 304 -
127.0.0.1 - - [13/Jun/2023 07:46:17] "OPTIONS /openapi.yaml HTTP/1.1" 200 -
127.0.0.1 - - [13/Jun/2023 07:46:17] "GET /openapi.yaml HTTP/1.1" 304 -
127.0.0.1 - - [13/Jun/2023 07:46:52] "OPTIONS /compile HTTP/1.1" 200 -
Request: POST /compile {'code': 'parent(john, jim).\nparent(jim, tim).\ngrandparent(X, Z) :- parent(X, Y), parent(Y, Z).'}
Code:  parent(john, jim).
parent(jim, tim).
grandparent(X, Z) :- parent(X, Y), parent(Y, Z).
True
[{'Errors': []}]
127.0.0.1 - - [13/Jun/2023 07:46:53] "POST /compile HTTP/1.1" 200 -
127.0.0.1 - - [13/Jun/2023 07:49:26] "OPTIONS /compile HTTP/1.1" 200 -
Request: POST /compile {'code': 'parent(john, jim).\nparent(john, ann).\nparent(mary, jim).\nparent(mary, ann).\nparent(jim, tim).\nparent(jim, amy).\nparent(ann, bob).\nparent(ann, sue).\nparent(bob, dan).\ngrandparent(X, Z) :- parent(X, Y), parent(Y, Z).\nsibling(X, Y) :- parent(Z, X), parent(Z, Y), X \\= Y.\naunt_uncle(X, Y) :- sibling(X, Z), parent(Z, Y).\ncousin(X, Y) :- parent(Z, X), parent(W, Y), sibling(Z, W).'}
Code:  parent(john, jim).
parent(john, ann).
parent(mary, jim).
parent(mary, ann).
parent(jim, tim).
parent(jim, amy).
parent(ann, bob).
parent(ann, sue).
parent(bob, dan).
grandparent(X, Z) :- parent(X, Y), parent(Y, Z).
sibling(X, Y) :- parent(Z, X), parent(Z, Y), X \= Y.
aunt_uncle(X, Y) :- sibling(X, Z), parent(Z, Y).
cousin(X, Y) :- parent(Z, X), parent(W, Y), sibling(Z, W).
True
[{'Errors': []}]
127.0.0.1 - - [13/Jun/2023 07:49:27] "POST /compile HTTP/1.1" 200 -
127.0.0.1 - - [13/Jun/2023 07:58:53] "OPTIONS /compile HTTP/1.1" 200 -
Request: POST /compile {'code': 'my_list([a, b, c, d, e]).\nmember(X, [X|_]).\nmember(X, [_|T]) :- member(X, T).'}
Code:  my_list([a, b, c, d, e]).
member(X, [X|_]).
member(X, [_|T]) :- member(X, T).
True
[{'Errors': []}]
127.0.0.1 - - [13/Jun/2023 07:58:54] "POST /compile HTTP/1.1" 200 -

Prompt
ChatGPT May 24 Version

Can you write a Prolog program that defines a parent-child relationship? Let’s say that John is the parent of Jim, and Jim is the parent of Tim. Then, define a rule to determine if someone is a grandparent.

Completion

Sure, here is a simple Prolog program that defines the parent-child relationship and a rule to determine if someone is a grandparent.

prolog

% Define parent-child relationships
parent(john, jim).
parent(jim, tim).

% Define grandparent rule
grandparent(X, Z) :- parent(X, Y), parent(Y, Z).

This program defines two facts: that John is the parent of Jim, and that Jim is the parent of Tim. It also defines a rule for grandparent: a person X is a grandparent of a person Z if there is some person Y such that X is a parent of Y and Y is a parent of Z. In this case, John is the grandparent of Tim.

Let’s compile this code using the SWI-Prolog plugin to ensure it’s correct.

json

{
  "code": "parent(john, jim).\nparent(jim, tim).\ngrandparent(X, Z) :- parent(X, Y), parent(Y, Z)."
}

Used SWI-Prolog REPL

LOCALHOST

REQUEST TO SWI-PROLOG REPL

{ "code": "parent(john, jim).\nparent(jim, tim).\ngrandparent(X, Z) :- parent(X, Y), parent(Y, Z)." }

RESPONSE FROM SWI-PROLOG REPL

{ "Errors": [], "success": true }

The Prolog code compiled successfully without any errors. Now, you can use this program to query the grandparent-child relationship. For example, you can ask if John is a grandparent of Tim by using the query grandparent(john, tim). The program should return true because, according to the facts we defined, John is indeed a grandparent of Tim.


Prompt

Create a more complex example of Prolog code.

Completion

Sure, let’s create a more complex family tree using Prolog. We’ll define parent-child relationships for a larger family and add rules to determine siblings, aunts/uncles, and cousins.

prolog

% Define parent-child relationships
parent(john, jim).
parent(john, ann).
parent(mary, jim).
parent(mary, ann).
parent(jim, tim).
parent(jim, amy).
parent(ann, bob).
parent(ann, sue).
parent(bob, dan).

% Define grandparent rule
grandparent(X, Z) :- parent(X, Y), parent(Y, Z).

% Define sibling rule
sibling(X, Y) :- parent(Z, X), parent(Z, Y), X \= Y.

% Define aunt/uncle rule
aunt_uncle(X, Y) :- sibling(X, Z), parent(Z, Y).

% Define cousin rule
cousin(X, Y) :- parent(Z, X), parent(W, Y), sibling(Z, W).

This program defines a more complex family tree and rules for determining various family relationships. The sibling rule states that two people are siblings if they share a parent and are not the same person. The aunt_uncle rule states that a person is an aunt or uncle of another person if they are siblings with that person’s parent. The cousin rule states that two people are cousins if their parents are siblings.

Let’s compile this code using the SWI-Prolog plugin to ensure it’s correct.

json

{
  "code": "parent(john, jim).\nparent(john, ann).\nparent(mary, jim).\nparent(mary, ann).\nparent(jim, tim).\nparent(jim, amy).\nparent(ann, bob).\nparent(ann, sue).\nparent(bob, dan).\ngrandparent(X, Z) :- parent(X, Y), parent(Y, Z).\nsibling(X, Y) :- parent(Z, X), parent(Z, Y), X \\= Y.\naunt_uncle(X, Y) :- sibling(X, Z), parent(Z, Y).\ncousin(X, Y) :- parent(Z, X), parent(W, Y), sibling(Z, W)."
}

Used SWI-Prolog REPL

LOCALHOST

The Prolog code compiled successfully without any errors. Now, you can use this program to query various family relationships. For example:

  • You can ask if Jim and Ann are siblings by using the query sibling(jim, ann). The program should return true because, according to the facts we defined, Jim and Ann are indeed siblings.
  • You can ask if John is an uncle of Bob by using the query aunt_uncle(john, bob). The program should return false because John is not Bob’s uncle.
  • You can ask if Tim and Bob are cousins by using the query cousin(tim, bob). The program should return true because Tim and Bob are indeed cousins according to the facts we defined.

Prompt

Do a quick Prolog example.

Completion

Sure, here’s a quick example of a Prolog program that defines a simple list and a rule to check if an element is a member of that list.

prolog

% Define a list
my_list([a, b, c, d, e]).

% Define a rule to check if an element is a member of the list
member(X, [X|_]).
member(X, [_|T]) :- member(X, T).

This program defines a list my_list with elements a, b, c, d, e. It also defines a rule member that checks if an element X is a member of a list. The rule works by checking if X is the first element of the list (the head), and if not, it recursively checks the rest of the list (the tail).

Let’s compile this code using the SWI-Prolog plugin to ensure it’s correct.

json

{
  "code": "my_list([a, b, c, d, e]).\nmember(X, [X|_]).\nmember(X, [_|T]) :- member(X, T)."
}

Used SWI-Prolog REPL

LOCALHOST

REQUEST TO SWI-PROLOG REPL

{ "code": "my_list([a, b, c, d, e]).\nmember(X, [X|_]).\nmember(X, [_|T]) :- member(X, T)." }

RESPONSE FROM SWI-PROLOG REPL

{ "Errors": [], "success": true }

The Prolog code compiled successfully without any errors. Now, you can use this program to query if an element is a member of the list my_list. For example, you can ask if b is a member of my_list by using the query member(b, my_list). The program should return true because, according to the list we defined, b is indeed a member of my_list.