Como xAI ha publicado finalmente un API público, hemos implementado una nueva Clase TGrok para Harbour y FWH.
Incluida en el próximo build de FWH.
Class TGrok
samples\grok1.prg
Incluida en el próximo build de FWH.
Class TGrok
#include "FiveWin.ch"
#include "hbcurl.ch"
//----------------------------------------------------------------------------//
CLASS TGrok
DATA cKey INIT ""
DATA cModel INIT "grok-3-latest"
DATA cPrompt
DATA cResponse
DATA cUrl
DATA hCurl
DATA nError INIT 0
DATA nHttpCode INIT 0
DATA nTemperature INIT 0.5
METHOD New( cKey, cModel )
METHOD Send( cPrompt )
METHOD SendStream( cPrompt, bCallback )
METHOD SendImage( cImageFileName, cPrompt )
METHOD SendImageURL( cImageUrl, cPrompt )
METHOD End()
METHOD GetValue()
DESTRUCTOR Destroy()
ENDCLASS
//----------------------------------------------------------------------------//
METHOD New( cKey, cModel ) CLASS TGrok
if Empty( cKey )
::cKey = GetEnv( "XAI_API_KEY" )
if Empty( ::cKey )
MsgAlert( "XAI_API_KEY not found" )
endif
else
::cKey = cKey
endif
if ! Empty( cModel )
::cModel = cModel
endif
::cUrl = "https://api.x.ai/v1/chat/completions"
::hCurl = curl_easy_init()
return Self
//----------------------------------------------------------------------------//
METHOD End() CLASS TGrok
if ::hCurl != nil
curl_easy_cleanup( ::hCurl )
::hCurl = nil
endif
return nil
//----------------------------------------------------------------------------//
PROCEDURE Destroy() CLASS TGrok
if ::hCurl != nil
::End()
endif
return
//----------------------------------------------------------------------------//
METHOD GetValue() CLASS TGrok
local hResponse, uValue
hb_jsonDecode( ::cResponse, @hResponse )
TRY
uValue = hResponse[ "choices" ][ 1 ][ "message" ][ "content" ]
CATCH
uValue = hResponse[ "error" ]
END
return uValue
//----------------------------------------------------------------------------//
METHOD Send( cPrompt ) CLASS TGrok
LOCAL aHeaders, cJson, hRequest := { => }, hSystemMessage := { => }, hUserMessage := { => }
if ! Empty( cPrompt )
::cPrompt = cPrompt
endif
curl_easy_setopt( ::hCurl, HB_CURLOPT_POST, .T. )
curl_easy_setopt( ::hCurl, HB_CURLOPT_URL, ::cUrl )
aHeaders = { "Content-Type: application/json", ;
"Authorization: Bearer " + ::cKey }
curl_easy_setopt( ::hCurl, HB_CURLOPT_HTTPHEADER, aHeaders )
curl_easy_setopt( ::hCurl, HB_CURLOPT_USERNAME, '' )
curl_easy_setopt( ::hCurl, HB_CURLOPT_DL_BUFF_SETUP )
curl_easy_setopt( ::hCurl, HB_CURLOPT_SSL_VERIFYPEER, .F. )
hRequest[ "model" ] = ::cModel
hSystemMessage[ "content" ] = "You are Grok, created by xAI."
hSystemMessage[ "role" ] = "system"
hUserMessage[ "content" ] = ::cPrompt
hUserMessage[ "role" ] = "user"
hRequest[ "messages" ] = { hSystemMessage, hUserMessage }
hRequest[ "temperature" ] = ::nTemperature
hRequest[ "stream" ] = .F.
cJson = hb_jsonEncode( hRequest )
curl_easy_setopt( ::hCurl, HB_CURLOPT_POSTFIELDS, cJson )
::nError = curl_easy_perform( ::hCurl )
curl_easy_getinfo( ::hCurl, HB_CURLINFO_RESPONSE_CODE, @::nHttpCode )
if ::nError == HB_CURLE_OK
::cResponse = curl_easy_dl_buff_get( ::hCurl )
else
::cResponse := "Error code " + Str( ::nError )
endif
return ::cResponse
//----------------------------------------------------------------------------//
METHOD SendStream( cPrompt, bCallback ) CLASS TGrok
local aHeaders, cJson, hRequest := { => }, hSystemMessage := { => }, hUserMessage := { => }
curl_easy_setopt( ::hCurl, HB_CURLOPT_POST, .T. )
curl_easy_setopt( ::hCurl, HB_CURLOPT_URL, ::cUrl )
aHeaders = { "Content-Type: application/json", ;
"Authorization: Bearer " + ::cKey }
curl_easy_setopt( ::hCurl, HB_CURLOPT_HTTPHEADER, aHeaders )
curl_easy_setopt( ::hCurl, HB_CURLOPT_USERNAME, '' )
curl_easy_setopt( ::hCurl, HB_CURLOPT_SSL_VERIFYPEER, .F. )
hRequest[ "model" ] = ::cModel
hSystemMessage[ "content" ] = "You are Grok, created by xAI."
hSystemMessage[ "role" ] = "system"
hUserMessage[ "role" ] = "user"
hUserMessage[ "content" ] = cPrompt
hRequest[ "messages" ] = { hSystemMessage, hUserMessage }
hRequest[ "temperature" ] = ::nTemperature
hRequest[ "stream" ] = .T.
cJson = hb_jsonEncode( hRequest )
curl_easy_setopt( ::hCurl, HB_CURLOPT_POSTFIELDS, cJson )
curl_easy_setopt( ::hCurl, HB_CURLOPT_WRITEFUNCTION, bCallback )
::nError = curl_easy_perform( ::hCurl )
curl_easy_getinfo( ::hCurl, HB_CURLINFO_RESPONSE_CODE, @::nHttpCode )
if ::nError != HB_CURLE_OK
::cResponse := "Error code " + Str( ::nError )
endif
return ::cResponse
//----------------------------------------------------------------------------//
METHOD SendImage( cImageFileName, cPrompt ) CLASS TGrok
local aHeaders, cJson, cBase64Image, hSystemMessage := { => }, hUserMessage := { => }
if ! File( cImageFileName )
MsgAlert( "Image " + cImageFileName + " not found" )
return nil
endif
DEFAULT cPrompt := "What is in this image?"
cBase64Image = hb_base64Encode( memoRead( cImageFileName ) )
curl_easy_setopt( ::hCurl, HB_CURLOPT_POST, .T. )
curl_easy_setopt( ::hCurl, HB_CURLOPT_URL, ::cUrl )
aHeaders = { "Content-Type: application/json", ;
"Authorization: Bearer " + ::cKey }
curl_easy_setopt( ::hCurl, HB_CURLOPT_HTTPHEADER, aHeaders )
curl_easy_setopt( ::hCurl, HB_CURLOPT_USERNAME, "" )
curl_easy_setopt( ::hCurl, HB_CURLOPT_DL_BUFF_SETUP )
curl_easy_setopt( ::hCurl, HB_CURLOPT_SSL_VERIFYPEER, .F. )
hSystemMessage[ "role" ] = "system"
hSystemMessage[ "content" ] = "You are Grok, created by xAI."
hUserMessage[ "role" ] = "user"
hUserMessage[ "content" ] = { ;
{ "type" => "text", "text" => cPrompt }, ;
{ "type" => "image_url", ;
"image_url" => { "url" => "data:image/jpeg;base64," + cBase64Image } } }
cJson = hb_jsonEncode( { "model" => ::cModel, ;
"messages" => { hSystemMessage, hUserMessage }, ;
"temperature" => ::nTemperature, ;
"stream" => .F. } )
curl_easy_setopt( ::hCurl, HB_CURLOPT_POSTFIELDS, cJson )
::nError = curl_easy_perform( ::hCurl )
curl_easy_getinfo( ::hCurl, HB_CURLINFO_RESPONSE_CODE, @::nHttpCode )
if ::nError == HB_CURLE_OK
::cResponse = curl_easy_dl_buff_get( ::hCurl )
else
::cResponse = "Error code " + Str( ::nError )
endif
return ::cResponse
//----------------------------------------------------------------------------//
METHOD SendImageURL( cImageUrl, cPrompt ) CLASS TGrok
local aHeaders, cJson, hRequest := { => }, hSystemMessage := { => }, hUserMessage := { => }
DEFAULT cPrompt := "What is in this image?"
curl_easy_setopt( ::hCurl, HB_CURLOPT_POST, .T. )
curl_easy_setopt( ::hCurl, HB_CURLOPT_URL, ::cUrl )
aHeaders = { "Content-Type: application/json", ;
"Authorization: Bearer " + ::cKey }
curl_easy_setopt( ::hCurl, HB_CURLOPT_HTTPHEADER, aHeaders )
curl_easy_setopt( ::hCurl, HB_CURLOPT_USERNAME, "" )
curl_easy_setopt( ::hCurl, HB_CURLOPT_DL_BUFF_SETUP )
curl_easy_setopt( ::hCurl, HB_CURLOPT_SSL_VERIFYPEER, .F. )
hRequest[ "model" ] = ::cModel
hRequest[ "temperature" ] = ::nTemperature
hRequest[ "stream" ] = .F.
hSystemMessage[ "role" ] = "system"
hSystemMessage[ "content" ] = "You are Grok, created by xAI."
hUserMessage[ "role" ] = "user"
hUserMessage[ "content" ] = { ;
{ "type" => "text", "text" => cPrompt }, ;
{ "type" => "image_url", "image_url" => { "url" => cImageUrl } } }
hRequest[ "messages" ] = { hSystemMessage, hUserMessage }
cJson = hb_jsonEncode( hRequest )
curl_easy_setopt( ::hCurl, HB_CURLOPT_POSTFIELDS, cJson )
::nError = curl_easy_perform( ::hCurl )
curl_easy_getinfo( ::hCurl, HB_CURLINFO_RESPONSE_CODE, @::nHttpCode )
if ::nError == HB_CURLE_OK
::cResponse = curl_easy_dl_buff_get( ::hCurl )
else
::cResponse = "Error code " + Str( ::nError )
endif
return ::cResponse
//----------------------------------------------------------------------------//// Remember to set from CMD: set XAI_API_KEY=sk-...
#include "FiveWin.ch"
//----------------------------------------------------------------------------//
function Main()
local oGrok := TGrok():New()
oGrok:Send( "Tell me France capital" )
MsgInfo( oGrok:GetValue() )
return nil
//----------------------------------------------------------------------------//