I’ve setup and installed a plugin which connects gpt to a woocommerce grocery store. Something’s not right though. I’m only getting ResponseTooLargeError as respons when the plugin searches the connected website. Seems that there might perhaps be an issue with the connection overall.
I tried deploying through the ChatGPT plugin page, but I’m getting an error – it’s not detecting the YAML file. Any suggestions?
I’ve been working with getting familiar with how chatgpt plugins work for the last few days, and using this woocommerce plugin as a way to learn and experiment. I’ve managed to set it up and it retrieves data although I still have to be very specific in how I formulate my inputs, otherwise I get a ResponseTooLargeError.
In general it seems that the ResponseTooLargeError occurs when I use a more diverse input. For example, if I ask “I need to purchase coffee” it generally understands 8/10 times. But if I say “I’m in the need to stock up on some basic products, coffee etc.” I almost immediately get a ResponseTooLargeError.
When I look at the Request made to the plugin in these cases the response is either completely empty or has a limit set such as:
{
"limit": 5
}
To add to the possible complexity this is a non-english woocommerce store serving customers in primary language swedish and secondary language finnish.
Background information about the store is that it is based in Finland, it is an online grocerystore with home delivery, and it has about 3000 active items in the shop. Just like basic grocery.
My biggest issue at the moment is the need to be super specific to get any respons. The language issue also seem to confuse GPT a bit, as it can only find for example one coffee related product when I ask in english but when I ask in swedish it gives me plenty.
The ResponseTooLargeError is a symptom of a wider confusion on GPTs side than an actual problem with the response being too large. It just doesn’t know what it is supposed to do so it just goes crazy and searches anything and everything and adds random limits in its requests.
Work in progress this one and I’ll update with current code stack if someone else is looking to build something similar or is able to spot some things that don’t look right.
This is my openapi.yaml description code:
openapi: 3.0.1
info:
title: WooCommerce Grocery Store Plugin
description: A plugin for getting meal suggestions, generating a shopping cart, searching for products, finding best deals, and exploring new products based on the WooCommerce grocery store inventory using ChatGPT.
version: 'v1'
servers:
- url: https://www.bodenbox.fi
paths:
/wp-json/custom-api/v1/search-products:
get:
operationId: searchProducts
summary: Search for products by name
parameters:
- in: query
name: search_term # Updated parameter name
schema:
type: string
description: The search term to find products by name
responses:
"200":
description: OK
content:
application/json:
schema:
type: object
properties:
products:
type: array
items:
type: object
properties:
name:
type: string
url: # Add the url property
type: string
format: uri
price:
type: number
format: float
on_sale:
type: boolean
regular_price:
type: number
format: float
discount_percent:
type: integer
image_url: # Add the image_url property
type: string
format: uri
description: The list of products (name, price, on_sale status, regular_price, and discount_percent) matching the search term
/inventory:
get:
operationId: getInventory
summary: Get the list of available items in the inventory
parameters:
- name: limit
in: query
description: Limit the number of items returned
required: false
schema:
type: integer
minimum: 1
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/getInventoryResponse'
/meal-suggestions:
post:
operationId: getMealSuggestions
summary: Get meal suggestions based on inventory and user preferences
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
preferences:
type: object
properties:
diet:
type: string
allergies:
type: array
items:
type: string
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/getMealSuggestionsResponse'
/generate-shopping-cart:
post:
operationId: generateShoppingCart
summary: Generate a shopping cart based on approved meal suggestions
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
approved_meals:
type: array
items:
type: string
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/generateShoppingCartResponse'
components:
schemas:
getInventoryResponse:
type: object
properties:
items:
type: array
items:
type: object
properties:
name:
type: string
quantity:
type: integer
description: The list of available items in the inventory.
getMealSuggestionsResponse:
type: array
items:
type: object
properties:
name:
type: string
ingredients:
type: array
items:
type: string
description: The list of meal suggestions based on inventory and user preferences.
generateShoppingCartResponse:
type: object
properties:
shopping_cart:
type: array
items:
type: object
properties:
name:
type: string
quantity:
type: integer
description: The generated shopping cart based on approved meal suggestions.
This is the code I have added on the server side for the wordpress themes functions.php file:
// Register a custom REST API route for searching products by name.
add_action('rest_api_init', function () {
register_rest_route('custom-api/v1', '/search-products', array(
'methods' => 'GET',
'callback' => 'search_products_by_name',
'args' => array(
'search_term' => array(
'required' => true,
'type' => 'string',
),
),
));
});
// Callback function for the custom REST API route.
function search_products_by_name($request) {
$search_term = $request->get_param('search_term');
$args = array(
'post_type' => 'product',
'posts_per_page' => -1,
's' => $search_term,
);
$query = new WC_Product_Query($args);
$products_objects = $query->get_products();
$product_data = array();
foreach ($products_objects as $product) {
// Get product URL
$product_url = $product->get_permalink();
// Get product image URL
$image_id = $product->get_image_id();
$image_url = wp_get_attachment_image_url($image_id, 'full');
// Calculate regular and sale prices including VAT
$regular_price_incl_vat = wc_get_price_including_tax($product, array('price' => $product->get_regular_price()));
$formatted_regular_price = number_format($regular_price_incl_vat, 2, '.', '');
$sale_price_incl_vat = $regular_price_incl_vat;
if ($product->is_on_sale()) {
$sale_price_incl_vat = wc_get_price_including_tax($product, array('price' => $product->get_sale_price()));
}
$formatted_sale_price = number_format($sale_price_incl_vat, 2, '.', '');
// Calculate discount percentage
$discount_percent = 0;
if ($product->is_on_sale() && $regular_price_incl_vat > 0) {
$discount_percent = (($regular_price_incl_vat - $sale_price_incl_vat) / $regular_price_incl_vat) * 100;
$discount_percent = round($discount_percent);
}
$product_data[] = array(
'name' => $product->get_name(),
'url' => $product_url, // Add the product URL to the response
'price' => floatval($formatted_sale_price),
'on_sale' => $product->is_on_sale(),
'regular_price' => floatval($formatted_regular_price),
'discount_percent' => $discount_percent,
'image_url' => $image_url
);
}
return $product_data;
}
And this is my current manifest file:
{
"schema_version": "v1",
"name_for_human": "Bodenbox GPT Plugin",
"name_for_model": "BodenboxGPT",
"description_for_human": "This plugin enables ChatGPT to interact with the Bodenbox WooCommerce store.",
"description_for_model": "This plugin helps people interact with the inventory in the woocommerce online grocerystore on https://www.bodenbox.fi. The plugin can provide information about products, products currently on sale, and prepare ready made shopping carts containing relevant products based on user input.",
"auth": {
"type": "user_http",
"authorization_type": "bearer"
},
"api": {
"type": "openapi",
"url": "https://www.bodenbox.fi/openapi.yaml",
"is_user_authenticated": false
},
"logo_url": "https://www.bodenbox.fi/wp-content/uploads/2023/04/logo-bodenbox.png",
"contact_email": "XXX",
"legal_info_url": "https://www.bodenbox.fi/anvandarvillkor/"
}
I was at one point thinking of using a split function to divide requests into smaller parts based on character limit but that seems to be a bit of clumsy way to solve this problem.
That path would be adding this to the functions.php file.
function split_input_into_smaller_parts($input, $limit = 100) {
$words = preg_split('/\s+/', $input);
$parts = [];
$current_part = '';
foreach ($words as $word) {
$proposed_part = empty($current_part) ? $word : $current_part . ' ' . $word;
if (strlen($proposed_part) <= $limit) {
$current_part = $proposed_part;
} else {
$parts[] = $current_part;
$current_part = $word;
}
}
if (!empty($current_part)) {
$parts[] = $current_part;
}
return $parts;
}
This is in swedish but I’ll explain. When writing in swedish, GPT output
A. tends sometimes to randomly change currency of output to swedish crones currency instead of euros.
B. produce results in post response that are completely unrelated to the results in the JSON response.
I ask GPT to find me a product from a specific producer (any product) and add it to a shopping cart. But the add to cart request is not formatted correctly in my opinion, it doesn’t include any identification of the product so it produces an error.
After a few days of debugging and developing I now have a working WooCommerceGPT plugin. Development is still ongoing and some minor bugs needs sorting (that might be specific to my environment and Wordpress / Woocommerce versions and setup).
The following files have been created / edited during the process:
1. functions.php
: This file contains the PHP code for the custom WordPress plugin. It includes the code for registering custom REST API endpoints, handling requests, and performing actions such as searching for products, adding products to the cart, and getting the cart contents.
2. custom-cart.js
: This JavaScript file contains the client-side code for interacting with the custom REST API endpoints. It includes functions for updating the session, adding products to the cart, and getting the cart contents. This file is enqueued and loaded on the front-end of the website.
3. add-to-cart-intermediary.php
: This PHP file is a custom page template that acts as an intermediary for adding products to the cart. It retrieves product IDs and quantities from the URL query parameters, adds the specified products to the WooCommerce cart, and then redirects the user to the cart page.
4. openapi.yaml
: This YAML file contains the OpenAPI specification for the custom REST API. It describes the available endpoints, request parameters, response formats, and other details about the API. This file is used by ChatGPT to understand how to interact with the API.
These files work together to enable ChatGPT to interact with the WooCommerce store, search for products, add products to the cart, and retrieve cart contents. The custom REST API endpoints provide the necessary functionality, while the JavaScript code and OpenAPI specification facilitate the interaction between the front-end and the API.
I am still having issues retrieving cart content via REST API but hopefully that is soon sorted. After setting up the basic functionality I can now move on to finetune the ChatGPT Woo plugin according to my specific needs.