Skip to content
Draft
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 111 additions & 0 deletions docs/how-to/how-to-run-examples.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# How to run the examples

## How to generate the example files

In order to use the examples provided in `OpenAIExamples`,
you'll need to have some examples files available locally.

To create all required files you can execute:

```smalltalk
OpenAIExamples new generateExampleFiles
```

This will create, inside the *open-ai* directory:

- answers-example.jsonl
- classifications-example.jsonl
- file-that-will-be-deleted.jsonl
- fine-tune-example.jsonl
- search-example.jsonl

## How to configure your API key

Before running the examples, you must provide a valid API key.

1. [Sign up](https://beta.openai.com/signup) for an OpenAI account.

2. Go to your
[API keys](
https://beta.openai.com/account/api-keys
)
and click on the *Create new secret key* button.

3. Click on the *Copy* link next to your recently created key.

4. Create a file named *apikey.secret* in the *open-ai* directory.

5. Paste the copied key into the file, then save it.

## How to invoke the APIs with the examples

Several examples are provided which show a possible use case for the diferent APIs.

The example methods return an object that extract the relevant answer
from the full API respose.
This is intended for the examples to illustrate how to navigate the structure
of the responses of the different APIs wrapped.

### Files API

Examples using the [Files API](https://beta.openai.com/docs/api-reference/files)

OpenAI offers by default 1 GB storage *per organization*.
For individual users this means 1 GB as well.
There is no cost associated with managing files.
This means that running the examples in this section will not reduce
your free balance.

Files are uploaded asynchronously.
Uploading returns a *File ID* than can be used later to check the file status.
You can't use a file until it's status is **processed**.

All uploads in the examples will wait up to 20 seconds, polling every second,
until the upload is complete.

Running `OpenAIExamples new files` will list the files currently registered.
In case you have not yet made any upload, the example will upload `open-ai/fine-tune-example.jsonl`.

Running `OpenAIExamples new downloadAndRemoveFile` will upload `open-ai/file-that-will-be-deleted.jsonl`.
After uploading is complete, the file will be deleted.
This is just meant to show the steps to both upload and delete a file.

Running `OpenAIExamples new deleteAllFiles` will **delete all files**
declared to your OpenAI account.
**Always use this example with caution**.

### Answers API

Examples using the [Answers API](https://beta.openai.com/docs/api-reference/answers)

Running `OpenAIExamples new answers` will ask *where is France?'*
using as context the information `France is in Europe` and
`Canada is in America` and `Japan is in Asia`.
To explain to OpenAI how to extract information from context,
it will provide the example that given the context `this car is 2 meters long`
and the question `how long is this car` the answer should be `2 meters`.
This use case does not employ the Files API, all processing is done in the moment.

Running `OpenAIExamples new answersFromFile` will do the same,
but the context is provided by the file `answers-example.jsonl`.
The file is uploaded, and then the question is asked to OpenAI.

### Search API

Examples using the [Search API](https://beta.openai.com/docs/api-reference/searches)
OpenAIExamples new search .
OpenAIExamples new searchFromFile .

### Completions API

Examples using the [Completions API](https://beta.openai.com/docs/api-reference/completions)
OpenAIExamples new completions .

### Classifications API

Examples using the [Classifications API](https://beta.openai.com/docs/api-reference/classifications)

OpenAIExamples new classifications .
OpenAIExamples new classificationsFromFileWithoutLabels .
OpenAIExamples new classificationsFromFile .

133 changes: 124 additions & 9 deletions source/Open-AI-Examples/OpenAIExamples.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,16 @@ OpenAIExamples >> answersAPIClient [
^ apiClient
]

{ #category : #'private - accessing' }
OpenAIExamples >> answersExampleFileReference [

^ self examplesDirectory / 'answers-example.jsonl'
]

{ #category : #'private - accessing' }
OpenAIExamples >> answersFileId [

^ self idForFileNamed: 'open-ai/answers-example.jsonl' intendedFor: 'answers'
^ self idForFileNamed: self answersExampleFileReference intendedFor: 'answers'
]

{ #category : #accessing }
Expand Down Expand Up @@ -95,10 +101,16 @@ OpenAIExamples >> classificationsAPIClient [
^ apiClient
]

{ #category : #'private - accessing' }
OpenAIExamples >> classificationsExampleFileReference [

^ self examplesDirectory / 'classifications-example.jsonl'
]

{ #category : #'private - accessing' }
OpenAIExamples >> classificationsFileId [

^ self idForFileNamed: 'open-ai/classifications-example.jsonl' intendedFor: 'classifications'
^ self idForFileNamed: self classificationsExampleFileReference intendedFor: 'classifications'
]

{ #category : #accessing }
Expand Down Expand Up @@ -164,6 +176,67 @@ OpenAIExamples >> completionsAPIClient [
^ apiClient
]

{ #category : #'private - processing' }
OpenAIExamples >> convertToLinuxLineEndings: aString [

^ ( aString copyReplaceAll: String crlf with: String lf ) copyReplaceAll: String cr with: String lf
]

{ #category : #'private - processing' }
OpenAIExamples >> createAnswersExampleFile [

self
write: '{"text": "France is in Europe", "metadata": "country with french people"}
{"text": "Canada is in America", "metadata": "country with canadian people"}
{"text": "Japan is in Asia", "metadata": "country with japanese people"}'
to: self answersExampleFileReference
]

{ #category : #'private - processing' }
OpenAIExamples >> createClassificationsExampleFile [

self
write:
'{"text": "good film, but very glum.", "label": "Positive", "metadata": {"source":"example.com"}}
{"text": "i sympathize with the plight of these families, but the movie doesn''t do a very good job conveying the issue at hand.", "label": "Negative", "metadata": {"source":"example.com"}}'
to: self classificationsExampleFileReference
]

{ #category : #'private - processing' }
OpenAIExamples >> createExamplesDirectory [

self examplesDirectory createDirectory
]

{ #category : #'private - processing' }
OpenAIExamples >> createFileThatWillBeDeleted [

self
write: '{"prompt": "<prompt text>", "completion": "<ideal generated text>"}'
to: self fileThatWillBeDeletedReference
]

{ #category : #'private - processing' }
OpenAIExamples >> createFineTuneExampleFile [

self
write: '{"prompt": "<prompt text>", "completion": "<ideal generated text>"}'
to: self fineTuneExampleFileReference
]

{ #category : #'private - processing' }
OpenAIExamples >> createSearchExampleFile [

self
write: '{"text": "a cat is happy", "metadata": "a type of feline"}
{"text": "a dog is hungry", "metadata": "a type of canine"}
{"text": "a car is loud", "metadata": "a type of vehicle"}
{"text": "a building is tall", "metadata": "a type of location"}
{"text": "a vehicle is fast", "metadata": "a type of transport"}
{"text": "a person is smart", "metadata": "a type of sentient being"}'
to: self searchExampleFileReference
]

{ #category : #accessing }
OpenAIExamples >> deleteAllFiles [

Expand All @@ -183,10 +256,22 @@ OpenAIExamples >> downloadAndRemoveFile [

| id |

id := self idForFileNamed: 'open-ai/file-that-will-be-deleted.jsonl' intendedFor: 'fine-tune'.
id := self idForFileNamed: self fileThatWillBeDeletedReference intendedFor: 'fine-tune'.
^ self filesAPIClient removeFileIdentifiedBy: id
]

{ #category : #'private - accessing' }
OpenAIExamples >> examplesDirectory [

^ 'open-ai' asFileReference
]

{ #category : #'private - accessing' }
OpenAIExamples >> fileThatWillBeDeletedReference [

^ self examplesDirectory / 'file-that-will-be-deleted.jsonl'
]

{ #category : #accessing }
OpenAIExamples >> files [

Expand All @@ -197,7 +282,7 @@ OpenAIExamples >> files [
^ files data
ifEmpty: [
Array with: ( apiClient
idForProcessed: 'open-ai/fine-tune-example.jsonl' asFileReference
idForProcessed: self fineTuneExampleFileReference
intendedFor: 'fine-tune'
waiting: 4 seconds )
]
Expand All @@ -213,19 +298,36 @@ OpenAIExamples >> filesAPIClient [
]

{ #category : #'private - accessing' }
OpenAIExamples >> idForFileNamed: aName intendedFor: aPurpose [
OpenAIExamples >> fineTuneExampleFileReference [

^ self examplesDirectory / 'fine-tune-example.jsonl'
]

{ #category : #processing }
OpenAIExamples >> generateExampleFiles [

self createExamplesDirectory.
self createAnswersExampleFile.
self createClassificationsExampleFile.
self createFileThatWillBeDeleted.
self createFineTuneExampleFile.
self createSearchExampleFile
]

{ #category : #'private - accessing' }
OpenAIExamples >> idForFileNamed: aFileReference intendedFor: aPurpose [

| fileName filesAPIClient files |

fileName := aName asFileReference basename.
fileName := aFileReference basename.
filesAPIClient := self filesAPIClient.
files := filesAPIClient listFiles.

^ files data
detect: [ :file | file filename = fileName ]
ifFound: [ :file | file id ]
ifNone: [
filesAPIClient idForProcessed: aName asFileReference intendedFor: aPurpose waiting: 4 seconds ]
filesAPIClient idForProcessed: aFileReference intendedFor: aPurpose waiting: 20 seconds ]
]

{ #category : #accessing }
Expand Down Expand Up @@ -253,10 +355,16 @@ OpenAIExamples >> searchAPIClient [
^ apiClient
]

{ #category : #'private - accessing' }
OpenAIExamples >> searchExampleFileReference [

^ self examplesDirectory / 'search-example.jsonl'
]

{ #category : #'private - accessing' }
OpenAIExamples >> searchFileId [

^ self idForFileNamed: 'open-ai/search-example.jsonl' intendedFor: 'search'
^ self idForFileNamed: self searchExampleFileReference intendedFor: 'search'
]

{ #category : #accessing }
Expand All @@ -278,3 +386,10 @@ OpenAIExamples >> sortByScoreDataIn: response [

^ ( response at: 'data' ) sorted: [ :a :b | ( a at: 'score' ) >= ( b at: 'score' ) ]
]

{ #category : #'private - processing' }
OpenAIExamples >> write: aString to: aFileReference [

aFileReference writeStreamDo: [ :stream |
stream nextPutAll: ( self convertToLinuxLineEndings: aString ) ]
]