Category Archives: Tech_Friday

Say Hello to ChatGPT with Powershell

ChatGPT, Bard, and other AI models are fun. A good way to dig into their capability and limitations are to access them via their API or applications programming interface. From what I’ve seen, many examples of this are in Python. So far, I hadn’t seen much for Powershell…so I thought it would be interesting to say hello to ChatGPT using Powershell.

Like any API, you need to establish an authorization code which identifies you to the API and which allows billing. The authcode essentially serves as a name and password for your call to ChatGPT. First you have to create an account:

Sign Up for OpenAI API

To sign up for the OpenAI API, visit OpenAI’s website and fill out the form. Once your request is approved, you’ll receive an invitation to join the API.

Get an API Key

After you’ve been accepted into the API, you’ll need to generate an API key. To do this, navigate to the API Dashboard and click on the “Generate API Key” button. Your key will be a string of alphanumeric numbers about 48 characters long.

Choose your model

OpenAI has several different models going back from ChatGPT4. Each model is a little different. Some are supposed to be more suitable for things like chatbots, others are better for searching, and of course the graphic model Dall-E generates (argueably horrible) pictures. For purposes of our sample here…. we’ll use the “text-Davinci-03” model which is an earlier version of the ChatGPT3 series.

Powershell Code to Connect:

The Powershell Code uses the PowerShell Invoke-RestMethod cmdlet, and its use is surprisingly similar to other API calls for other services. Here is the full code:

$headers = @{
‘Content-Type’ = ‘application/json’
‘Authorization’ = ‘Bearer yourAPICodeGoesHere12334455’
}

$body = @{
prompt = ‘Hello ChatGPT!’
temperature = 0.7
model = ‘text-davinci-003’
}

$bodyjson= ConvertTo-Json -inputobject $body

$response = Invoke-RestMethod -Uri ‘https://api.openai.com/v1/completions’ `
-Method ‘POST’ `
-Headers $headers `
-Body $bodyjson

 

The prompt parameter specifies the text prompt to send to the model. The temperature parameter controls the “creativity” of the response, with higher values generating more novel responses. The model parameter specifies which model to use – in this case, text-davinci-003.

It works! Run the Powershell script, and you’ll get the following:

‘Hi there! How can I help you today?

API Documentation

You can find more information about the text-davinci-003 model in the OpenAI API documentation. The documentation provides details on the available parameters, example responses, and more.

Payment and Charges

It’s worth noting that to use the OpenAI API, you’ll need to provide a payment method and will be charged an initial $5.00. More information on payment and charges can be found on the API pricing page.

JSON for PowerShell Part 1

JSON, otherwise known as “Javascript object notation” is a fundamental way of representing key/value pairs. In database terms this translates as a field name (the key) and the field contents (the value).

Let’s show a single contact record in JSON, with two phone numbers, work and home.

{    
"FName":"Myron", 
"Lname":"Kapoodle",
"Address1":"123 Anywhere Lane",
 "Address2":"Apartment 404",
 "City":"BigTown",
  "State":"AZ",
    "Zip":"12345",
    "PhoneNumbers":[       
 {"type":"home","number":"920 234-3424" },
 {"type":"work","number":"920 535-2312"  }
   ]
}

A couple of characteristics:

The complete JSON structure is enclosed in its own curly brackets
If there is more than one record, then the whole structure is contained with square brackets, and the individual records are separated by a comma. This applies to nested records too, as in the case of the two phone numbers for the individual.

Below is the notation for two contact records. In this case, the whole structure is enclosed in square brackets. The individual contact records are enclosed in curly brackets and the two records are separated by a comma.

[    
{"FName":"Myron",
 "Lname":"Kapoodle",
 "Address1":"123 Anywhere Lane",
 "Address2":"Apartment 404",
 "City":"BigTown",
 "State":"AZ",
"Zip":"12345",
"PhoneNumbers":[ {"type":
"home","number":"920 234 3424"},
"type":"work","number":"920 535-2312"}]
}
,
{
"FName":"Myra",
Lname":"Kapoodlova",
"Address1":"123 Anywhere Lane",
"Address2":"Apartment 404",
"City":"BigTown",
"State":"AZ",
"Zip":"12345",
"PhoneNumbers":[ {"typee":
"home","number":"920 234-3424"},
{"type":"work","number":"920 535-2312"}]
}
]

When writing JSON, its helpful to have an automatic checker for syntax. One such is JSONLint at http://jsonlint.com. In Visual Studio Code you can use the Shift-Alt-F within the editor to nicely format JSON code.

The rules of JSON are summarized at JSONLint, but basically include:

  • Keys are enclosed in double quotes.
  • All data elements that are not a boolean or integers are enclosed in double-quotes.
  • Individual entities (i.e. records) are separated by a comma
  • Each key/value pair is separated by a comma
  • Each entity is enclosed by curly brackets.

Since I’m editing JSON in Visual Studio Code, there is more how VSC handles JSON in the Microsoft docs at JSON editing in Visual Studio Code.

Powershell has a two commands that deal directly with JSON.

PS M:\PSFolder> get-command *json*     

CommandType     Name                    Version    Source
-----------     ----                    -------    ------
Cmdlet          ConvertFrom-Json        3.1.0.0    Microsoft.PowerShell.Utility
Cmdlet          ConvertTo-Json          3.1.0.0    Microsoft.PowerShell.Utility


These convert Powershell objects to and from JSON notation. More on that in Part 2.

Install PowerShell Core on the Mac

My ancient iMac, late 2012,  is still able to use the latest and greatest MacOS. At this writing, it is running MacOS Mojave 10.14.2, and I’m trying to install PowerShell Core 6.0 with Visual Studio Code on the machine.

PowerShell Core 6.0 is the open source cross-platform version of Microsoft PowerShell for Windows, and is available for Windows, Linux and the Mac.  In hindsight,  it might make more sense to test this all out on a Linux virtual machine before mucking up the MacOS.

The first thing to do is to install a package manager called Homebrew on to the Mac. This is the package manager which interfaces with GitHub to fetch the packages necessary for PowerShell.

Homebrew is available at: https://brew.sh    It gives you a command line to insert in the Mac terminal program which runs a script to fetch and install the Homebrew package manager.

Before pasting the command within the terminal prompt, you need to create a terminal session with “elevated” or root permissions.

Start Terminal

type su <your account name>   that is,  the command “su” and you’re user account.

You’ll be prompted for a password,  put in your Mac password.

On my machine this returns a prompt on the command line of bash-d.2$ At this point, I can paste the command below, and Homebrew will be installed.  The installation took about ten minutes.

Once the installation is complete,  you’ll see a message within the terminal:

Now that we have the package manager installed, we can go ahead and install Powershell

bash-3.2$ brew cask install powershell

This downloads the files from GitHub  Accoring to the prompts this will be version 6.1.

Once the packages are downloaded,  you’ll be prompted again for the root password:

and now, if you type pwsh you can start powershell which returns a prompt PS

type $psversiontable to see the current version.

FileMaker: One to Many Reports

FileMaker is great for putting together a quick form for any number of data-entry chores.  By using a FileMaker portal you can put together a master/detail form that will keep track of transactions based on some kind of header record.  Typical examples include:

  • Invoices and line items
  • Customers and interactions
  • Prospects and sales efforts.
  • Jobs and application sequence.

These forms are especially helpful when you need to keep track of a “pipeline”.   For example when applying for a job, there are multiple steps involved:

  • Applied for the job
  • Received an eMail acknowledgement
  • First phone interview
  • Second phone interview
  • Scheduled live interview

At any one time you may have multiple jobs somewhere in the process, and a typical status report would show a list of each job and its current status.

This brings us  back to the question of displaying the jobs and activities. We’re looking for a “report” which has a list of jobs, and underneath each job the list of activities that have taken place for the job.

JobHunt FileMaker portals display the related records for each master record but a portal almost by definition shows only a specific number of transactions at a time in a scrollable window.  For a printed report, where we want to see all of the related records, we need to define the report without the portal.  This is done using FileMaker’s “sub summary” band when creating the report layout.  The trick is to start defining the report using the transaction table as the basis of the report displaying the fields in the body band and referencing the master table in the sub summary band.  When setting this up,  it looks something like this:

JobHunt2.png

Note the report bands on the extreme left,  with the body band at the bottom, the sub summary above it,  and the report header band at the top.   One clue that the basis of the report is the transaction table is that at the top of the screen, it shows “Table:Transactions” .  Also, the reference to the related field in the subsummary band are prefaced with the double colonon.

The ::RprtHeader  field is actually a calculated field which consists of the employer’s name, and the job being advertised by the employer.  This solves the problem of applying to more than one job at a single employer, in that it effectively provides a unique field name to display the transactions for just one job at a time.

 

 

Install Ubuntu 16.04 on VirtualBox

The following is a step-by-step run through for installing Ubuntu 16.04 server as a virtual machine running under a Windows 10 host.  Two prerequisites:

Prepare the VirtualBox VM:

Click on “New” to create a new virtual machine: You’ll get this initial screen to choose the operating system you wish to install and choose a name for the your VM.

Ubuntu Install1.jpg

The next screen asks what you want to RAM memory. The recommended memory size is 768MB,  but I’ve had decent luck by boosting this to 4 gigs, (on my 8 gig Windows 10 workstation.).

UbuntuInstallMemory.jpg

Accept the next suggestion to create a virtual hard disk. The default 8GB is fine, because VirtualBox will expand this if necessary.

UbuntuHD.jpg

Accept the default next screen, to choose the file type.

VirtualHardDisk.jpg

… and accept the default “dynamically allocated”

DiskFixedSize.jpg

 

Finally you can choose the file size:

FileSize.jpg

In this case,  I chose 16 gigabytes.

Once you have completed the screens above, you need to change two other parameters before starting the actual installation:

Under Settings,  change the networking connection to “bridged adapter”

NetworkSettings.jpg

Under storage, point the little CD image to your .iso file.

StorageSettins.jpg

 

Install Ubuntu 16.04

At this point you are ready to start the VM, and go through installing Ubuntu from the .iso file.  This is the standard Ubuntu installation from here on out… run from a  console command line interface. Terminal.jpg

After making your keyboard and language selections, there are several prompts for additional information:

Choose a HostName: UBSandbox

Choose an initial account: larryk

Choose a login name for this account: larryk

Choose a password: mypassword

Encrypt your  home directory?  No

Set your time zone. Setup will suggest your local timezone and then ask
Is this time zone correct?   Yes

Partitioning Method:  Choose “Use Entire Disk”,  don’t worry about LVN

Select Disk to partition…. choose the defaults.

Write changes to disk? Yes

At this point the files are copied to the disk, and the installation continues ore or less on its own for five minutes or so,  then you’ll see a question about the use of an http proxy. This relates to the configuration for the package manager which is used to update the operating system. You can probably ignore this unless you know you are in a corporate environment that uses an http proxy server.

Proxy.jpg

The next screen asks you about updating. I would answer this with the default “no automatic updates”. .

Updates.jpg

Finally there is a screen that allows you to select additional software packages to be installed. I would include the LAMP server, and the OpenSSH server.  LAMP will be the usual Linux+Apache web server + PHP + mySQL

install.jpg

But wait! There’s more!   You will be asked for a password for the  mySQL database. Ignore this at your peril…and choose the same password as you used for your user account at the beginning of your installation.

mysqlpassword.jpg

At this point the installation will run for a few minutes and then …

Will this ever end?   Accept the default ‘Yes” to install the GRUB boot loader.

grubboot.jpg

And then….  we’re done.

alldone.jpg

At this point, you should have a working web server that is running an IP address on your network.  To figure out that address. run ifconfig from the VM console.  In our case we’re at 192.168.219.213

ifconfig.jpg

Looks promising.  Now,  we can open a web browser from our Windows workstation (or any other machine on the network, and we should see the Apache web server home screen.

Screenshot_111816_125839_PM.jpg

We’re ready install WordPress.  Before doing that however, you might create a snapshot* of the current state of the VM.  This means we will always have a backup of the current machine that we can fall back to as we’re experimenting with installing things. If you haven’t already installed Ubuntu three or four times, you can always delete the whole VM and reinstall if you want to start from square 1.

 

*I know….this is for a future blog post.

Install WordPress Using VirtualBox Part 2

Because WordPress is such a popular program, there are tons of resources available. After searching for installing WordPress on Ubuntu Server … I found this page.  I followed all of the instructions, with the two exceptions:

  • I did not configure a static IP address for the sandbox server.
  • I prefaced all commands with sudo.

 Once this was accomplished,  I ended up with the default installation page at:

192.168.219.212/wordpress/

wordpress_install

The first page that comes up is a page which asks for information which will will be written to the wp-config file.   Note that all of the parameters are identical to the ones that were used when setting up the mySQL database in the initial step.

wpsetup

The next page asks for the WordPress site name, and a login password.

wpinstall2

About 30 seconds later, you should see a message that WordPress was installed, and that you can now log in with the name and password that you just created in the last screen.  Do that and the familiar WordPress dashboard will come up.  Hooray!

wpdashboard

Install WordPress Using VirtualBox Part 1

Now that we’re WordPress experts,  I’m looking to get an instance of WordPress up and running to be able to experiment.  I’ve been trying this using VirtualBox on Windows 10.  I wanted to create a virtual web server using the latest Ubuntu server 16.04.

  1. Download the .iso file from Ubuntu
  2. Create a new virtual machine, “Ubuntu Server 16.04” within VirtuaBox. I gave it 4 gigs of RAM (half of the physical RAM in my workstation), and excepted all defaults for disk size, etc. The only difference afterwards is to change the Network Adapter from NAT to Bridged.virtualbox1

    3. Install Ubuntu. 
    During the Ubuntu installation, choose the option to install a LAMP server. This includes mySQL, the Apache web server, and the PHP language.

linux_install

4. Once Ubuntu is installed, the server will reboot. You will probably see that there are updates available.  So, to get these run the following commands:

sudo apt-get update
sudo apt-get upgrade

5. Figure out your local IP address:

ifconfig

If this address isn’t on your own subnet, then you can change the network specifications for the VM in VirtualBox from NAT to Bridged Adapter, then reboot the VM.

If all is well so far, you should see the Apache default home page when you type in the ip address into your browser.

apachedefault

At this point, we have a working web server running on our virtual machine.  Now we can actually install WordPress.  My first instinct for this was to use the apt-get method to install the files.

sudo apt-get install wordpress

This appeared to work but didn’t yield a running installation. So after searching I used these instructions to get to get a running WordPress installation.

 

Donation Processing with Stripe

Our site is based on WordPress.  We had a link to a PayPal donation page that we used for awhile. On recommendation by another organization we created an account at Stripe and are converting our online payment processing to Stripe.

We have a WordPress plugin called “Full Stripe” which handles the transactions.We went ahead and paid for the “pro” version of the plugin.

The Full Stripe plugin hosts the donation form. This is placed on a  regular WordPress page (i.e., not a post.).  stripeform

Once the form is filled out, and the credit card is successfully charged, the form will automatically take the user to a thank-you page.

The plugin generates a thank-you email which is sent to the email address that the donor puts into the form.  This email can be customized using regular html.  Right now there isn’t a very elegant way of editing or testing within  the email so  I did all the editing in Notepad++ and then pasted the resulting html into the plugin’s eMail form.

After some fiddling we got the form, the thank-you page, and the thank-you eMail all set.

YAPI (Yet Another Plugin)

For the plugin to be able to email donor receipts, it has to be able to access an SMTP server. In our case, we’re using Google Apps for Work, so that we installed a GMail plugin that overrides the PHP mail code inherent in WordPress.  The receipts are sent from a gmail account on our domain.  This took just a few minutes to set up and has a form for testing.

Review

So,  let’s review all of the bits and pieces necessary for the full solution:

  • Stripe – an account with Stripe connected to your bank account.
  • The WordPress Full Stripe plugin.  We purchased Full Stripe, and have been pleased with the enhanced capability over the free version as well as prompt and knowledgeable tech support. (Actually, we love the developer’s company name….Mammothology  Software…. we’d purchase anything from them.  🙂 )
  • The donation form.  This form is defined using parameters that are set by the Full Stripe plugin.  Right now the options are fairly modest in terms of formatting and fields, but the appearance is attractive and clean.
  • The donation page.  This is a WordPress page  that contains a WordPress shortcode pointing to the donation form defined in the Full Stripe Plugin.
  • The Thank-You Page.  This is another WordPress page that serves as a landing page after the donor successfully fills in the form and completes their transaction.
  • The Gmail plugin.  — Needed to send email from our Google Apps for Work domain.
  • The Thank-You email.   This is a personalized email sent to the donor.  The html code for this is defined within the plugin.  As noted,  I tested this with code written in Notepad++ (on Windows) and TextWrangler on the Mac.
  • The Stripe Thank-You email.   This is a second email that comes from Stripe which shows the last 4 digits of the credit card, and that fact that the card was successfully charged.

Progress with MailClark, Slack, FileMaker, WordPress

Somemotor-1381998_1280times you just have a week where you are grinding away at things, and nothing particularly new or spectacular happens, and no new revelations are on the horizon. This was one of those weeks.

MailClark and Slack

The MailClark experiment is moving into its third week. As I hoped, it  appears to be working well as an application for low-volume  email customer support. In another couple of weeks, I will introduce this to the rest of the customer support team, so that more than one of us can respond to emails and questions sent in to our help address.

FileMaker CRM

Our FileMaker CRM is taking shape. I have built the basic tables, and am working on the data entry screens. I’ve hosted it on a new Mac Mini with an SSD drive using FileMaker Server. This is the first time I’ve ever used an SSD up close and personal (all Linodes are SSD based), and I’m impressed with the speed.

FileMaker has been steadily improving the web client of the application called WebDirect. This is an effective implementation of the regular FileMaker desktop interface, but rendered in HTML5 and CSS for a web browser, which eliminates the need to install the FileMaker software client on your desktop workstation.  My thought is that we will provide access to the CRM via a virtual private networking connection rather than allowing direct access through our firewall.

Similar to FileMaker Go, the FileMaker client that runs on iPhones and iPads, I  expect to build dedicated data entry screens for the web clients. This means that each platform gets its  own screens….desktop,  iDevice, and web.  The startup script for the application will contain a CASE statement which determines which platform you are connecting with, and point you to the correct screen.

So far the data design and use cases appear to be pretty accurate and for the most part remain unchanged. One thing I have done is add a “reference” section. This will provide a front-end for the National Center for Educational Statistics database of public and private schools.

WordPress and Apache

I spent a couple days faffing about with my Apache / WordPress installation, trying to figure out what what slowing down our blog. It turns out to be hidden in plain sight, and here is one explanation.

 

Troubleshoot Apache with mod_status

We are having a bit of a contretemps with one our of Linode blog hosts. This host is running Ubuntu Linux 12X  LTS and WordPress, and seems to be having fits of high CPU utilization. One way to see into the web hosting process is to examine the Apache mod_status page.

Mod_status is an Apache module which prints statistics about the Apache application. By default the page will be accessible using the the suffix of /server-status on your root web site URL. http://mysite.com/server-status. However, by default this is restricted to a request from a browser at the 127.0.0.1 address.

If you log into the console, you can attempt to see the status by running the following:

apachectl status

or if you aren’t logged in as root,

sudo apachectl status

This returns the status page.

Screenshot_071516_011101_PM

If you are attempting to access this from a browser on another workstation via http://mysite.com/server-status, you get a 403 message:

Screenshot_071516_110946_AM

The first thing is to find where this restriction is located. It is going to be in one of the Apache configuration files. These are located within /etc/apache2. If the status module is enabled, there will be a status.conf file that can be edited.

sudo nano  /etc/apache2/mods-enabled/status.conf

Screenshot_071516_112041_AM

Edit the lines after the <Location /server-status> line, per the instructions. After editing mine looked like:

<Location /server-status>
   SetHandler server-status
   #Require local 
   Require ip 192.168.xxx.0/24
</Location>

where “xxx” is your local subnet.  In the above example, I’m accessing the server from inside the firewall from a workstation located on the same subnet as the Apache server. (In reality, I’m actually accessing a server running within a VirtualBox virtual machine, located on my Windows machine. )

Once these changes are made you have to restart Apache.

service apache2 restart

 

If this is successful,  you get a page similar to the character-based page, but nicely formatted in html. Since the data is similar, however, if there is any issue trying to get at the statistics, probably the character-based method at the console is the first thing to try.

Screenshot_071516_011525_PM

Ah…but what if you get a page, but it isn’t a status page?  This is the problem we have with our WordPress site, and it has to do with which page is served as the default. http://myblog.com/server-status  returns the default page from the blog rather than the server-status page.  Stay tuned for that fix.