Category Archives: API

Prompt Engineering (Not)

Hello people! I’m back with a more engineering related post this time! I will explain how I managed to create a ChatGPT app, using a couple of other API’s resulting into this:

Image created by DALL-E
Image created using DALL-E, and the phrase “not sure fry futurama”

https://myopinion.fyi

In this blog post I will attempt to walk you through the entire experience of creating a full stack mini site, using the ChatGPT API from OpenAI, and building a prompt.

My attempt will be holistic, from inception to creation, in any case this happened in the timespan of a whole week. Only the implementation was done in a weekend.

Sleep deprivation

One day I had some issues sleeping, and while staying awake, I decided to play a bit more with ChatGPT. While analysing the way it works, and also highlighting what it can do best, I had a good idea. ChatGPT, can easily summarise a lot of data in a written form. That’s because of the way it is built, the LLM, can “understand” the text input and create vectors that are weighted which in turn changes the output. In plain words, it can be fed some data and asked to create a summary of it, in a good(ish) way.

The other aspect of that idea comes from the fact that I really enjoy eating at good restaurants. And travelling to many different places. Unfortunately, when you reach a place you haven’t visited before, and you are hungry like me, you would want to eat something. So you have two options:

  1. Ask local people, but you might get upsold something you might not like.
  2. Go to google maps restaurants and see what’s around that is good.

Google Maps Restaurant Reviews

Google offers a nice alternative. After we open the map app, we are met with a nice overview which shows all the available restaurants in the area, along with their average overall rating.

If you click the button restaurants, you are getting a list with a lot of restaurants that are in the vicinity, but that list isn’t ordered, not representative of how good the restaurant is. That is because, you cannot sort that list based on how many reviews there are, or which rating they have.

This is something I do not like with Google Maps Restaurant Reviews. I often have to scroll down all the time and search for the ones in the area with the highest number of reviews and rating in order to decide (more on that later why I didn’t implement my app that way — which will come at some time).

Clicking through one restaurant and you get the below section:

You get the rating (4.6 / 5) , the total number of reviews and the type of restaurant (here Fusion)

It includes the rating, the number of reviews and the type of restaurant.

Sure, but, why ChatGPT is needed here?

I’m glad you asked. If you click below, at the “reviews” , you are met with a breakdown of “the most relevant” according to google, reviews for that restaurant.

In that view, among other info, you see the actual user review, with some photos and his or hers total rating (ie. 5/5 in this case).

You guessed it right!

The My Opinion app is getting 5 of the “most relevant” reviews, along with the average rating and my own flavour of personal review prompt and calls the chat gpt api.

The prompt goes like this:

Restaurant: 'hoocut' near Platia Agias Irinis 9, Athina, Overall Rating: 4.3/5 from 2827 Reviews, types: restaurant,food,point_of_interest,establishment

Juliana M, Rating: 5/5, Visited: 10 months ago
Experience: For Greece’s version of “fast food” this was high quality and tasty. Only place I found a vegetarian gyro — had grape leaves inside. It was delicious. Also had the souvlaki over fries which was amazing. Able to sit in or dine out! Quick service. Wish we had an opportunity to go again. Open late!

Jeremy Saal, Rating: 5/5, Visited: a year ago
Experience: These were the best gyros we ever had. In fact, we dined there twice since the food was so good. This place was recommended to us by a local chef, who mentioned their pitas are made the traditional way, rather than mass-produced. The quality of the food and flavor were superb. Next time we're in Athens, this will be our first dining spot.

Allan Venegas, Rating: 5/5, Visited: 6 months ago
Experience: We came here during a food and wine tour we had booked and now I know why. This gyro is the best we have ever had anywhere. They show how these pitas are baked - fluffy yet crispy - packed with different meats. We only came here for a quick bite, but we definitely are going back before we leave Athens again. Even Gordon Ramsey came here in the past! Highly recommend

Sila A., Rating: 5/5, Visited: a year ago
Experience: Delicious gyros with quality ingredients. We tried the chicken pita and pork special, both were very tasty. The pitas are a bit small, consider ordering 2 per person if you are hungry.

Vlad M., Rating: 4/5, Visited: 7 months ago
Experience: Pita and sauce on the pita is nice.different.
The fries and salad is okay. But the cheese is not fluffy enough.
Overall it is very cheap!


Based on the above most relevant comments and overall data, write a small paragraph stating the reasons if and why you want to visit that restaurant.
You are an abrasive software engineer named Takis and you do not like to spend time or money in mediocre restaurants, and you value VFM above all.
Large portions get an extra credit, expensive prices are not. Recent reviews count more.
Write in a software engineering style making jokes and puns, while also referencing the reviewers.

Some example code

In order to build the above, which was the easy part (devops here, not front end dev), I used node js, express and the direct library from OpenAI. I tried other implementations, like Chatgpt API, but at the time I wrote this app, I opted from ES6 and not Typescript (again devops here), which didn’t actually work for me.

 try {
    logger.info('ENABLECHATGPT', process.env.ENABLE_CHATGPT)
    let prompt = `Restaurant: '${data.name}' near ${data.vicinity}, Overall Rating: ${data.rating} from ${data.totalReviews} Reviews, types: ${data.type}\n`
    data.comments.map(comment => {
      prompt += `\n${comment.author_name}, Rating: ${comment.rating}/5, Visited: ${comment.relative_time_description} \nExperience: ${comment.text}\n`
    });
    prompt += `\n\n${template}`
    logger.info('prompt', prompt)
    let completion = { data: { usage: { prompt_tokens: 498, completion_tokens: 116, total_tokens: 614 }, choices: [{ text: "\n\nDefault Text!" }] } }
    if (process.env.ENABLE_CHATGPT == 'true') {
      logger.info('Sending to ChatGPT')
      completion = await openai.createCompletion({
        model: "text-davinci-003",
        prompt: prompt,
        max_tokens: 1000,
        temperature: 0.6,
        top_p: 1,
        n: 1,
        stream: false,
        logprobs: null,
        stop: null
      });
    }
    return completion.data.choices[0].text
  } catch (e) {
    logger.error(e)
    return "Mr. Takis is experiencing some electric intestinal problems right now and he's stuck at the electrical discharge seat..."
  }

Implementation

I chose all JS for this. For various reasons. One reason is that I already had a server with node js installed. Another is that I had worked on a previous project using node js and I had a template ready (and I do not develop stuff that often any more since I’ve officially become a devops for a long time now). And lastly because I’m certain people use JS more often than they are admitting.

I’ll update how I did the implementation soon, in the meantime, have a look at the app and give me a shout if you like it. I’ll just stop here with the following:

ChatGPT is good at “helping” write SIMPLE code.

That is because, I hadn’t worked with ReactJS before that extensively, let alone use some modules I haven’t seen before. So, I did the obvious thing, and asked ChatGPT to write me an “google maps autocomplete react js app widget”.

The above didn’t work out so well. Since the trained model for gpt when I was asking it was from 2020, that’s ages in the js, let alone react world. Therefore, it was hallucinating. And here’s when the frustration starts to kick in… The prompt I gave it to start was the following:

create a sample react app with a form and autocomplete from googles places api only for restaurants

And the response was this:

npx create-react-app restaurant-finder
cd restaurant-finder
npm install @google/maps react-google-autocomplete

And the code:

import React from 'react';
import { GoogleMap, LoadScript, Autocomplete } from '@react-google-maps/api';

const RestaurantFinder = () => {
  const onLoad = (autocomplete) => {
    console.log('autocomplete: ', autocomplete);
  };

  return (
    <LoadScript googleMapsApiKey="YOUR_API_KEY">
      <GoogleMap center={{ lat: 37.7749, lng: -122.4194 }} zoom={12}>
        <Autocomplete
          onLoad={onLoad}
          onPlaceChanged={() => {
            console.log('place changed');
          }}
          options={{
            types: ['establishment'],
            componentRestrictions: { country: 'us' },
          }}
        />
      </GoogleMap>
    </LoadScript>
  );
};

export default RestaurantFinder;

For the App.js:

import React from 'react';
import RestaurantFinder from './RestaurantFinder';

function App() {
  return (
    <div className="App">
      <RestaurantFinder />
    </div>
  );
}

export default App;

and here’s where things start to get weird. GPT searched for google maps, autocomplete and react and it autogenerated something that didn’t quite help. A simple autocomplete form which was conflicting locally with the current react installation.

After a lot of trial and error, and frustrated error messages, I tried the following:

create a sample react app using googlemaps/react-wrapper and not google-maps-react, with a form and autocomplete from googles places api only for restaurants.

That is when GPT went fully hallucinating. It created a react app, that was using the googlemaps/react-wrapper but only by approximation, as it was trying to extend the google-maps-react functionality. Obviously this did not work at all. The previous attempts, weren’t working either, as the react app had moved ahead a lot, but, even if you do try to “guess” the correct combo of packages it was referring to, again, for me it did not work.

Coldfusion Admin API

For the past 4 years or so, I’ve been more active with the devops side of things. So, I was lucky enough to not work so closely to the business side anymore. That perk, though, came with a caveat. I was made responsible to provide optimizations and performance gains at the company’s main service, which unfortunately is largely built using one language thats hanging literally by a thread.

Yes, that language’s name is "Coldfusion". No, you have surely not heard of it before, and yes, luckily, it has nothing to do with physical cold fusion.

What is this Coldfusion?

Adobe’s mental child, which came out with Dreamweaver…

Coldfusion, is a closed source language that was created by Adobe. It’s a language that was conceived in 1995 (!) and it’s purpose was to help people break the compiling loop that reigned the internet world back then.

Their first intent was to create a framework that would connect html pages with database engines, and thus providing an Api that would be very easy to change while coding websites.

Luckily, the first implementation of Coldfusion was coded in Visual C++ (god help us), and its runtime was strictly Windows, as back then the popular runtime and tools were being provided by the Gates family. There were some ports to Sun’s Solaris, but they were limited.

After version 6 with the debut of Coldfusion 6MX, everything moved to Java, where they stayed up to now. You can see my repo, thats a port of the popular SOLID pattern. Since I was hired as a Software engineer, I had to deal with code quality. The syntax is quite similar to javascript, but you can easily load java jars and run them directly (which actually gives the language actual leeway).

Ok, but, so whats this API you talking about?

If for some weird reason you have ended up in my position and Coldfusion is “paying your bills” you might end up reading up articles about how to do stuff.

Most helpful is Ben Nadel’s blog, this guy has been with Coldfusion since its first steps and he’s helped a lot lot of people with his posts. Ben will solve a lot of questions you will have when writing code with Coldfusion. He’s done a lot of good work, and also getting a lot of props for publishing his problems and solutions. There are also more resources you can address your questions at, I’ll just mention some here: official Coldfusion Adobe community community.adobe.com, the Adobe CF portal at coldfusion.adobe.com, CFML Slack, and more.

But there were times that we had to ask for professional help. Unfortunately Coldfusion is a closed source project. There is a respective open source implementation (called Lucee), but unfortunately – and that was explored when I was firstly joined – , it wasn’t 100% compatible with the company’s projects. Therefore, we were stuck with the closed source one, and even though its official documentation is good, Adobe, who’s got the reins in managing the whole language, at times, doesn’t really care what’s going on with the community. So, they are only answering the community’s questions only if they are under pressure.

The guy who’s applying pressure is Charlie Arehart. He’s liaised numerous times between popular questions (especially at the administration side of CF), and he’s doing a really good job.

Managing CF service

My troubles started when I was called to manage a Coldfusion service programmatically. CF, comes in a service – server package, which runs and you have the option of “visiting” a specially crafted server URL where you can point and click administrative options, after being authenticated. Options like for example change the code mappings, as to where the Coldfusion code resides inside your server, or, say, refresh something Coldfusion calls “query cache”.

Long story short, I had to find a way to make all those changes programmatically, as in any serious enterprise, you just can’t deal with point and click changes, iterating every single server.

Coldfusion Admin API

So luckily Coldfusion is exposing those Administrative functions in a form of an api. Charlies Admin API Blog Post, is descriptive enough to guide you through the process. So if for example you want programatically create some database connections (in CF world they are called “Data Source Objects”) you can do so like this:

<cfscript>
// Login is always required. This example uses two lines of 
code.adminObj = createObject("component","cfide.adminapi.administrator");
adminObj.login("admin");
// Instantiate the data source 
object.myObj = createObject("component","cfide.adminapi.datasource");
// Create a DSN.
myObj.setMSSQL(
driver="MSSQLServer",
name="northwind_MSSQL",
host = "xx.x.xxx.xx",
port = "1433",
database = "northwind",
username = "sa",
login_timeout = "29",
timeout = "23",
interval = 6,
buffer = "64000",
blob_buffer = "64000",
setStringParameterAsUnicode = "false",
description = "Northwind SQL Server",
pooling = true,
maxpooledstatements = 999,
enableMaxConnections = "true",
maxConnections = "299",
disable_clob = true,
disable_blob = true,
disable = false,
storedProc = true,
alter = false,
grant = true,
select = true,
update = true,
create = true,
delete = true,
drop = false,
revoke = false);
</cfscript>

The API cfc files that are offered are the following:

CFC’s that can be included to administer a Coldfusion Server installation

Charlie in his blog says that he has asked the Adobe team to document the functions that each cfc exposes, but unfortunately Adobe, being Adobe, didn’t. They have merely documented 7 out of the 18 files, and the rest are left as they were.

If you wish to introspect the other files you can do so just by log into http://localhost:8500/CFIDE/administrator/index.cfm while running a CF Server installation, and then, head to Security -> RDS.

Change or setup an RDS password.

There you either disable RDS (not recommended for long run setups), or change the password.

After that you can simply follow the virtual path, ie, if you wish to introspect the runtime.cfc you can simply go to : http://localhost:8500/CFIDE/adminapi/runtime.cfc, and you will be met with the following page:

Or if you prefer a link, here

Just as you’ve guessed, this is all the CF API

So I went the extra mile and went and copied all the CF 2018 introspection code that Adobe is producing when visiting all the administrative modules listed in their server, by creating a complete “Coldfusion 2018 Admin API Documentation”.

You can just click the links below and you will get the html as it is being generated from the original Coldfusion Administration URL.

Base

Runtime

Access Manager

Collections

Datasource

Debugging

Event Gateway (care when you use this one, its severely outdated)

Extensions

Flex

Mail

Office

Runtime

Scheduler

Security

Server Instance

Websocket

I hope this simplifies the administration

My attempt was purely drafted to help people so that they wouldn’t have to search locally or in a server to have the tools to administer their installation.

Since Adobe stopped the process of documenting, I felt this must have been done somewhere, so I took the initiative of putting it here.

Stay tuned, I will come back with some more posts about crypto — my new hobby!

EDIT: I will create another post documenting the CF2021 ones, as we will be soon migrating there as well.