DataFlex
DataFlex
Streaming AI with Manual AI Tool Function Calling
See more AI Examples
Demonstrates how to get AI responses in streaming mode, including manual tool function calls.Chilkat DataFlex Downloads
Use ChilkatAx-win32.pkg
Procedure Test
Boolean iSuccess
Variant vJsonTools
Handle hoJsonTools
Integer iToolIdx
Handle hoAi
String sConversation_name
String sSysMessage
String sDevMessage
Variant vSbEventName
Handle hoSbEventName
Variant vSbDelta
Handle hoSbDelta
Handle hoSbFullResponse
Integer iMaxWaitMs
Handle hoJsonFn
Boolean iFinished
Integer iNumAsks
Boolean iMadeFunctionCalls
Boolean iStreamingDone
Integer iResult
Integer iNumFnCalls
Integer iFn_idx
Variant vSbFnName
Handle hoSbFnName
String sCallId
String sZodiac_sign
String sApplicationFnCallResult
String sTemp1
Boolean bTemp1
Move False To iSuccess
// Create the following JSON to define tool functions available for the AI to use.
// Note: You'll use the following JSON format regardless of the AI provider, whether
// it be ChatGPT, Gemini, Claude, Grok, etc. Chilkat automatically converts to the required
// format needed for a given AI provider.
// In this example, the application is providing a single function the AI may choose to call.
// {
// "tools": [
// {
// "name": "get_horoscope",
// "description": "Get today's horoscope for an astrological sign.",
// "parameters": {
// "properties": {
// "sign": {
// "type": "string",
// "description": "An astrological sign like Taurus or Aquarius"
// }
// }
// }
// }
// ]
// }
Get Create (RefClass(cComChilkatJsonObject)) To hoJsonTools
If (Not(IsComObjectCreated(hoJsonTools))) Begin
Send CreateComObject of hoJsonTools
End
Move 0 To iToolIdx
Set ComI Of hoJsonTools To iToolIdx
Get ComUpdateString Of hoJsonTools "tools[i].name" "get_horoscope" To iSuccess
Get ComUpdateString Of hoJsonTools "tools[i].description" "Get today's horoscope for an astrological sign." To iSuccess
Get ComUpdateString Of hoJsonTools "tools[i].parameters.properties.sign.type" "string" To iSuccess
Get ComUpdateString Of hoJsonTools "tools[i].parameters.properties.sign.description" "An astrological sign like Taurus or Aquarius" To iSuccess
// More tools can be added as desired..
Set ComEmitCompact Of hoJsonTools To False
Get ComEmit Of hoJsonTools To sTemp1
Showln sTemp1
Get Create (RefClass(cComChilkatAi)) To hoAi
If (Not(IsComObjectCreated(hoAi))) Begin
Send CreateComObject of hoAi
End
// Register the tools that will be made available to the AI.
Get pvComObject of hoJsonTools to vJsonTools
Get ComRegisterManualTools Of hoAi vJsonTools To iSuccess
// The provider can be "openai", "google", "claude", "grok", "mistral", "custom", etc.
Set ComProvider Of hoAi To "openai"
// Use your provider's API key.
Set ComApiKey Of hoAi To "MY_API_KEY"
// Choose a model.
Set ComModel Of hoAi To "gpt-5-mini"
// Tool function calling must always occur within a conversation.
Move "convo_astrology" To sConversation_name
Move "You are a helpful astrologer" To sSysMessage
Move "Respond only with markdown." To sDevMessage
Get ComNewConvo Of hoAi sConversation_name sSysMessage sDevMessage To iSuccess
// Provide inputs
Get ComInputAddText Of hoAi "What is my horoscope? I am an Aquarius." To iSuccess
// Get the response in streaming mode.
Set ComStreaming Of hoAi To True
// In streaming mode, if we receive an AI event that is a request for tool use,
// we'll need to make the call to the JavaScript and then continue with a followup Ask,
// until the final response is received.
Get Create (RefClass(cComChilkatStringBuilder)) To hoSbEventName
If (Not(IsComObjectCreated(hoSbEventName))) Begin
Send CreateComObject of hoSbEventName
End
Get Create (RefClass(cComChilkatStringBuilder)) To hoSbDelta
If (Not(IsComObjectCreated(hoSbDelta))) Begin
Send CreateComObject of hoSbDelta
End
Get Create (RefClass(cComChilkatStringBuilder)) To hoSbFullResponse
If (Not(IsComObjectCreated(hoSbFullResponse))) Begin
Send CreateComObject of hoSbFullResponse
End
// When PollAi returns with an event, it's highly unlikely the
// call to NextAiEvent does not immediately return. Setting a max
// timeout is just a precaution..
Move 5000 To iMaxWaitMs
Get Create (RefClass(cComChilkatJsonObject)) To hoJsonFn
If (Not(IsComObjectCreated(hoJsonFn))) Begin
Send CreateComObject of hoJsonFn
End
Move False To iFinished
Move 0 To iNumAsks
// Set a max # of followup Asks to prevent any unexpected infinite looping.
While (Not iFinished And (iNumAsks < 10))
// Send the request to the AI model.
Get ComAsk Of hoAi "text" To iSuccess
If (iSuccess = False) Begin
Get ComLastErrorText Of hoAi To sTemp1
Showln sTemp1
Procedure_Return
End
Move False To iMadeFunctionCalls
Move False To iStreamingDone
While (Not iStreamingDone)
Get ComPollAi Of hoAi False To iResult
If (iResult < 0) Begin
Get ComLastErrorText Of hoAi To sTemp1
Showln sTemp1
Showln "Failed."
Procedure_Return
End
If (iResult > 0) Begin
// We have an event..
Get pvComObject of hoSbEventName to vSbEventName
Get pvComObject of hoSbDelta to vSbDelta
Get ComNextAiEvent Of hoAi iMaxWaitMs vSbEventName vSbDelta To iSuccess
If (iSuccess = False) Begin
Get ComLastErrorText Of hoAi To sTemp1
Showln sTemp1
Procedure_Return
End
// Is this an event where the AI is requesting a function call?
Get ComContentsEqual Of hoSbEventName "function_call" True To bTemp1
If (bTemp1) Begin
Get pvComObject of hoSbDelta to vSbDelta
Get ComLoadSb Of hoJsonFn vSbDelta To iSuccess
// Note: Chilkat will convert responses from all AI providers to this format:
// {
// "function_call": [
// {
// "name": "get_horoscope",
// "call_id": "call_RYmeysYQFocFc7Z2ofkv61dW",
// "arguments": "{\"sign\":\"Aquarius\"}",
// "args": {
// "sign": "Aquarius"
// }
// }
// ]
// }
Get ComSizeOfArray Of hoJsonFn "function_call" To iNumFnCalls
Move 0 To iFn_idx
While (iFn_idx < iNumFnCalls)
Set ComI Of hoJsonFn To iFn_idx
Get Create (RefClass(cComChilkatStringBuilder)) To hoSbFnName
If (Not(IsComObjectCreated(hoSbFnName))) Begin
Send CreateComObject of hoSbFnName
End
Get pvComObject of hoSbFnName to vSbFnName
Get ComStringOfSb Of hoJsonFn "function_call[i].name" vSbFnName To iSuccess
Get ComStringOf Of hoJsonFn "function_call[i].call_id" To sCallId
Get ComContentsEqual Of hoSbFnName "get_horoscope" True To bTemp1
If (bTemp1 = True) Begin
// The get_horoscope function (as defined above) has one argument named "sign".
Get ComStringOf Of hoJsonFn "function_call[i].args.sign" To sZodiac_sign
Showln "zodiac_sign = " sZodiac_sign
// Insert application code here to call your app's get_horoscope function, passing the zodiac_sign to it..
// For this example, we'll pretend the app's get_horoscope function returned the following:
Move "Aquarius: Next Tuesday you will befriend a baby otter." To sApplicationFnCallResult
// Provide the tool call result as an input for the followup Ask.
Get ComInputAddFnResult Of hoAi sCallId sApplicationFnCallResult To iSuccess
Move True To iMadeFunctionCalls
End
// Your application would add code to check for and handle each possible function call.
Move (iFn_idx + 1) To iFn_idx
Loop
End
Else Begin
Get ComContentsEqual Of hoSbEventName "empty" True To bTemp1
If (Not bTemp1) Begin
Get pvComObject of hoSbDelta to vSbDelta
Get ComAppendSb Of hoSbFullResponse vSbDelta To iSuccess
Get ComContentsEqual Of hoSbEventName "null_terminator" True To bTemp1
If (bTemp1) Begin
Move True To iStreamingDone
End
End
End
End
Else Begin
// No event arrived, so wait a short time rather than spin in a loop..
Send ComSleepMs To hoAi 100
End
Loop
If (Not iMadeFunctionCalls) Begin
Move True To iFinished
End
Move (iNumAsks + 1) To iNumAsks
Loop
Showln "Full Response:"
Get ComGetAsString Of hoSbFullResponse To sTemp1
Showln sTemp1
End_Procedure