B4A Class B4X - OpenAI - a class to work with OpenAI in your B4X-Project

This clas is based on the work of @Abdull Cadre and @JackKirk.

I got addicted and played a bit with OpenAI and added some Methods from the Api. ?
I also added the functionality in my Discord-Bot in my racing-league.

I would like to share the actual class here and also i try to give some help in implementing this Class.


Note that i developed the Class using B4J and use Windows-Path for the downloadfolder. change them to Androidspecific folders like File.DirInternal.

ATTENTION: Please note that OpenAI is not a free service if you want to use the Api, want to use your own Assistants.

Add a Environmentvariable OpenAItoken containing your ApiKey to your system. The ApiKey is read from Environment when Initializing the Class

Add the class to your project and Initialize it
B4X:
    Public AI As OpenAI
    AI.Initialize("org-Ucp") ' Set your OrganisationID here
    AI.Assistant = "asst_TQ..." ' Set your AssistantID here if you want to use the Assistant-API
    AI.Logfilepath = "C:\ORCBot\logs\OpenAI" ' Set logfilepath to a working path for logfiles. Set it to "" to disable logging


Class Methods:
- CreateAssistant
- CreateAssistantFile
- ModifyAssistant
- ListAssistants
- ListAssistantFiles
- UploadFile
- RetrieveMessage

- ChatCompletion
- CreateThread
- CreateRun
- RetrieveRun
- ListRunSteps
- CreateThreadAndRun

- createTranscription
- createSpeech

- QueryImage
 

Attachments

  • OpenAI.bas
    34.3 KB · Views: 200
Last edited:

DonManfred

Expert
Licensed User
Longtime User
Working with Assistants

To work with Assistants you have to fulfill some requirements.
- A Assistant can only work in a "Thread". So if you want to start parsing the input and run a (or some) Assistant you have to
1. Upload files which can be used in Assistants to your Assistant. Remember the fileID.
2. Create a new Thread
3. Add all relevant Messages to this thread
4. Create a run for this Thread and
5. wait for finishing the run.

The File i uploaded to my assistant is a JSONL-File. Means there are one Dataset in each LINE. The Data is JSON.
Note the first line which is the headerline. I gave my assistant the INSTRUCTION
"Du bist ein höflicher Assistent. Wenn Du eine Frage gestellt bekommst lieferst du den Wert aus Content vom Eintrag aus den Dateien mit der höchsten Relevanz im feld Kategorie zurück."
in english something like
"You are a kind Assistant. When you get asked a question you deliver the first value from Content from the entries in the Files with the highest relevance in the field Kategory back."

So the assistant with look at this file and get the most relevant KAPITEL and deliver the Value from Content in this Dataset.

["Kapitel", "Content"]
["Master", "Es ist doch wohl klar, dass ORC_DonManfred unser Gott der Bots ist. **ODER?**"]
["Mr MIMIMI", "Es ist hinlänglich bekannt, dass ORC_MIKE unser Mr. MI MI MI ist."]
The Method CreateThreadAndRun is a simple but complete Example of doing all these steps in just one.


B4X:
Public Sub CreateThreadAndRun(assistant_id As String, query_string As String, fileids As List) As ResumableSub
 
    'For complete documentation you should look at:
    'https://platform.openai.com/docs/api-reference/runs/createThreadAndRun
 
    Try
 
        ' Consider using 'gpt-4-turbo-preview', 'gpt-3.5-turbo', or a later model.",
        Dim model As String = "'gpt-3.5-turbo"
        Dim msgs As List
        msgs.Initialize
        'fileids
        Dim usermap As Map = CreateMap("role":"user","content":query_string)
        If fileids.IsInitialized And fileids.Size>0 Then
            usermap.Put("file_ids",fileids)
        End If
        msgs.Add(usermap)
        Dim thread As Map
        thread.Initialize
        thread.Put("messages",msgs)
      
        Dim m As Map = CreateMap("model":model,"assistant_id": assistant_id, "thread":thread)
        m.Put("stream",True)

        Dim jgen As JSONGenerator
        jgen.Initialize(m)
 

        'Uncomment this line if you want to see raw input string
        Log(jgen.ToString)

 
        Dim response As String
 
        Dim req As HttpJob
        req.Initialize("", Me)
        req.PostString("https://api.openai.com/v1/threads/runs", jgen.ToString)
        req.GetRequest.SetHeader("Authorization", "Bearer "&mtoken)
        'And if you have an organisation key...
        'If your account default organisation is "Personal" then you can supply
        'a blank organisation key - or just comment this line out
        'req.GetRequest.SetHeader("OpenAI-Organization", "org-xxx")
        req.GetRequest.SetHeader("OpenAI-Organization", morganization)
        req.GetRequest.SetHeader("OpenAI-Beta", "assistants=v1")
        req.GetRequest.SetContentType("application/json")
 
        Wait For (req) JobDone(req As HttpJob)
 
        If req.Success Then
    
            'Uncomment this line if you want to see raw JSON response
            Dim res As String = req.GetString
            'Log(res)
            response = res
            If mlogfilepath<> "" Then
                File.WriteString(mlogfilepath,$"Assistant-run-${DateTime.Now}.txt"$,res)
            End If

            'response = ParseJson(req.GetString)
 
        Else
    
            response = "ERROR: " & req.ErrorMessage
 
        End If
 
        req.Release
 
    Catch
 
        response = "ERROR: " & LastException
 
    End Try
 
    Return response

End Sub

Example of call
B4X:
    Dim fileids As List
    fileids.Initialize
    fileids.Add("file_xx...") ' add the fileID you want to use in this run in a per run basis.
   
    Wait For (AI.CreateThreadAndRun(AI.Assistant,"Was steht im Regelwerk zu Lackierungen?",fileids)) Complete (response As String)
    Log(response)

It will result in the following output



The line event: thread.message.completed and the followiing line is the important one.
 
Last edited:

DonManfred

Expert
Licensed User
Longtime User
Hi @DonManfred does anything prevent to use this with B4J?
no
Note that i developed the Class using B4J and use Windows-Path for the downloadfolder. change them to Androidspecific folders like File.DirInternal.

It should work in B4i as well.
 
Last edited:
Cookies are required to use this site. You must accept them to continue using the site. Learn more…