Introduction
OpenAI has significantly expanded the capabilities and customizability of generative AI models with the introduction of CustomGPTs1 and the subsequent launch of the GPT Store2. This advancement allows users to tailor ChatGPT models to specific needs, fostering a community of builders and users who share their custom versions for broader applications. Remarkably, in just two months following the announcement of GPTs, over three million custom versions have been created, culminating in the introduction of the GPT Store for enhanced accessibility and sharing among ChatGPT Plus, Team, and Enterprise users.
Demystifying Actions
While CustomGPTs offer extensive customization options, notably tailoring the model's behavior to perform specific tasks, a significant underutilized feature is the integration of actions. Actions enable CustomGPTs to interact with external APIs, opening up a realm of possibilities for dynamic and context-aware applications. This post aims to demystify the process of integrating actions into CustomGPTs, showcasing the potential through a practical application related to job descriptions.
Integrating actions with CustomGPT involves setting up an API that can communicate with external services. This requires providing credentials for authentication, if necessary, and creating an OpenAPI schema to describe the API's functionalities. Additionally, a privacy policy is essential for publishing your API, ensuring users' data is handled securely and transparently.
Case Study: CustomGPT for Job Descriptions
My CustomGPT project serves as a concrete example of the power of integrating actions with CustomGPT. The goal was to provide users with detailed task descriptions for various job titles, leveraging the comprehensive database offered by O*Net's web services3. O*Net provides over 19,000 task descriptions for more than 1,000 job titles, making it an invaluable resource for this application. Accessing this data requires credentials, which can be obtained by applying to O*Net.
An action for finding matching job titles
A significant challenge in utilizing O*Net's database is the variability of job titles. Users may not know or use the exact titles as listed in O*Net's database. To address this, I developed a solution that involves mapping arbitrary job titles to the closest matching titles in O*Net's database. This was achieved by setting up a cloud function in Google Cloud, which uses the OpenAI Embed API4 to create embeddings for all 1,016 job titles listed by O*Net. When a job title is queried, the cloud function computes the cosine distance between the query's embedding and the pre-computed embeddings to find the semantically closest match.
For this project, the following steps were undertaken:
Pre-processing O*Net Titles: Initially, all 1,016 job titles from the O*Net database were processed through the OpenAI Embed API to generate 1536-dimensional vectors for each title. For this I used the Python OpenAI API5 which requires an API key provided by OpenAI6. This one-time preprocessing step ensures that the embedding process does not need to be repeated for these titles.
Uploading Embeddings: The generated embeddings were then uploaded and stored in a way that they could be efficiently accessed by my Google Cloud Function7. For this I used a Python client library8 to access Google Cloud Storage9.
Finding the Semantic Match: When the cloud function receives an embedding for an input job title, it computes the cosine distance between this embedding and the stored embeddings of the O*Net job titles. Cosine distance measures the cosine of the angle between two vectors, serving as an indicator of similarity; the closer to 1, the more similar the vectors are10.
Returning the Best Match: The job title corresponding to the O*Net embedding with the highest cosine similarity (i.e., closest to 1) to the input job title's embedding is identified as the best match. This title is then sent back in response to the original request.
For the custom cloud function designed to map arbitrary job titles to their standardized counterparts in O*Net's database, I used an OpenAPI11 (yes, OpenAPI, not OpenAI!) YAML schema. This schema specifies how to send job titles to the cloud function and how it responds with the best-matching standardized job title.
Retrieving and Presenting Task Descriptions
With the accurately mapped job title, my CustomGPT can then retrieve the corresponding code for the job title from O*Net's publicly available website12. This is retrieved by the GPT via web search without action.
This code (e. g. 13-2011.00) is used to make an API request to O*Net, which returns a list of task descriptions for the job title (e. g. Accountants and Auditors). Here’s the corresponding OpenAPI schema (JSON):
These tasks are then presented to the user within the chat, offering valuable insights into the job's requirements and duties. This is an example of the resulting conversation from ChatGPT:
Try it out for yourself. Here is the link. I'm looking forward to your feedback!
Summary and Conclusion
The integration of actions into CustomGPTs unlocks a new dimension of possibilities, enabling models to interact with external data and services dynamically. By leveraging APIs, CustomGPTs can become even more powerful tools tailored to specific domains or tasks. The case study of creating a CustomGPT for job descriptions illustrates the practical steps and considerations involved in integrating actions, from handling variability in user input to setting up APIs for data retrieval. As the GPT Store continues to grow, offering a platform for sharing and discovering custom models, the potential for innovative and impactful applications of CustomGPTs is boundless.
https://openai.com/blog/introducing-gpts
https://openai.com/blog/introducing-the-gpt-store
https://services.onetcenter.org/
https://platform.openai.com/docs/guides/embeddings
https://github.com/openai/openai-python
You can create one after logging in your OpenAI account: https://platform.openai.com/api-keys
https://cloud.google.com/functions/docs/console-quickstart
https://cloud.google.com/storage/docs/reference/libraries
https://cloud.google.com/python/docs/reference/storage/latest/google.cloud.storage.client.Client#google_cloud_storage_client_Client_get_bucket
https://en.wikipedia.org/wiki/Cosine_similarity
https://spec.openapis.org/oas/v3.1.0
https://www.onetonline.org/find/all