Error al compilar ejemplos Gemini# con xHb

Post Reply
Enrrique Vertiz
Posts: 554
Joined: Fri Oct 07, 2005 2:17 pm
Location: Lima - Peru
Been thanked: 3 times
Contact:

Error al compilar ejemplos Gemini# con xHb

Post by Enrrique Vertiz »

Saludos

Compilando los ejemplos de FWH 25.01 con xHarbour 10288 en samples, compilan varios pero todos los gemini#.prg, me dan el error abajo adjunto

Image

Y los ollama# no me funcionan ... algo me falta ?
Enrrique Vertiz Pitta
Lima-Peru
xHb 1.23.1026X, Fwh 24.09, BCC74, MySQL 8.0.X, SQLLIB 1.9m
User avatar
Antonio Linares
Site Admin
Posts: 42575
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Has thanked: 36 times
Been thanked: 84 times
Contact:

Re: Error al compilar ejemplos Gemini# con xHb

Post by Antonio Linares »

Estimado Enrique,

Estamos terminando de adaptar los cambios más recientes de la Clase TGemini a xHarbour

Hoy al comenzar el webinar os daremos la versión más reciente de todas las Clases de Inteligencia Artificial para Harbour y xHarbour
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
Posts: 42575
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Has thanked: 36 times
Been thanked: 84 times
Contact:

Re: Error al compilar ejemplos Gemini# con xHb

Post by Antonio Linares »

Class TGemini para Harbour y xHarbour

Code: Select all | Expand

#include "FiveWin.ch"
#include "hbcurl.ch"

#ifdef __XHARBOUR__
   #define hb_hHasKey( h, k ) HHasKey( h, k )
#endif   

//----------------------------------------------------------------------------//

CLASS TGemini

   DATA   cKey   INIT ""
   DATA   cModel INIT "gemini-2.0-flash"
   DATA   cResponse
   DATA   cUrl   INIT "https://generativelanguage.googleapis.com/v1beta/models"
   DATA   cUploadUrl INIT "https://generativelanguage.googleapis.com/upload/v1beta/files"
   DATA   hCurl
   DATA   nError INIT 0
   DATA   nHttpCode INIT 0
   DATA   nTemperature INIT 0

   METHOD New( cKey, cModel )
   METHOD Send( uContent, cPrompt, bCallback )
   METHOD End()
   METHOD GetValue()
   METHOD UploadFile( cFileName, lDeleteAfter )
   METHOD GetTokens( cBuffer ) 

ENDCLASS

//----------------------------------------------------------------------------//

METHOD New( cKey, cModel ) CLASS TGemini

   if Empty( cKey )
      ::cKey = GetEnv( "GEMINI_API_KEY" )
   else
      ::cKey = cKey
   endif

   if ! Empty( cModel )
      ::cModel = cModel
   endif

   if Val( SubStr( Curl_Version_Info()[ 1 ], 1, RAt( ".", Curl_Version_Info()[ 1 ] ) - 1 ) ) - 8.10 > 0.2
      MsgAlert( "Please use an updated curl DLL" )
   endif    

   ::hCurl = curl_easy_init()

return Self

//----------------------------------------------------------------------------//

METHOD End() CLASS TGemini

   curl_easy_cleanup( ::hCurl )
   ::hCurl = nil

return nil

//----------------------------------------------------------------------------//

METHOD GetValue() CLASS TGemini

   local hResponse, uValue

   if ! Empty( ::cResponse )
      hb_jsonDecode( ::cResponse, @hResponse )
   endif

   if hb_isHash( hResponse )
      if hb_hHasKey( hResponse, "error" )
         uValue = "API Error: " + hResponse[ "error" ][ "message" ] + " (Code: " + hb_ntos( hResponse[ "error" ][ "code" ] ) + ")"
      elseif hb_hHasKey( hResponse, "candidates" ) .and. Len( hResponse[ "candidates" ] ) > 0
         TRY
            uValue = hResponse[ "candidates" ][ 1 ][ "content" ][ "parts" ][ 1 ][ "text" ]
         CATCH
            uValue = "Error: Unexpected response structure"
         END
      else
         uValue = "Error: No candidates in response"
      endif
   else
      uValue = "Error: Invalid response format"
   endif

return uValue

//----------------------------------------------------------------------------//

METHOD Send( uContent, cPrompt, bCallback ) CLASS TGemini

   local aHeaders, cJson, hRequest := {=>}, hContents := { => }, hGenerationConfig
   local cFileUri, cMimeType, lIsFile := .F., cUrlEndpoint
   local aFiles, nI, aParts := {}, cFileNameToUpload, cTempFile

   if Empty( cPrompt )
      cPrompt = "what is this or solve this"
   endif

   if hb_isArray( uContent )
      aFiles = uContent
      for nI = 1 to Len( aFiles )
         if hb_isChar( aFiles[ nI ] ) .and. File( aFiles[ nI ] )
            cFileNameToUpload = aFiles[ nI ]
            cTempFile = nil
            if Lower( Right( aFiles[ nI ], 3 ) ) == "prg"
               cTempFile = hb_FNameMerge( hb_FNameDir( aFiles[ nI ] ), hb_FNameName( aFiles[ nI ] ), "txt" )
               hb_FCopy( aFiles[ nI ], cTempFile )
               cFileNameToUpload = cTempFile
            elseif Lower( Right( aFiles[ nI ], 2 ) ) == "ch"
               cTempFile = hb_FNameMerge( hb_FNameDir( aFiles[ nI ] ), hb_FNameName( aFiles[ nI ] ), "txt" )
               hb_FCopy( aFiles[ nI ], cTempFile )
               cFileNameToUpload = cTempFile
            endif
            cFileUri = ::UploadFile( cFileNameToUpload, !Empty( cTempFile ) )
            if Empty( cFileUri )
               if !Empty( cTempFile ) .and. File( cTempFile )
                  hb_FileDelete( cTempFile )
               endif
               return "Error uploading file: " + aFiles[ nI ]
            endif
            do case
               case Lower( Right( aFiles[ nI ], 3 ) ) == "png"
                  cMimeType = "image/png"
               case Lower( Right( aFiles[ nI ], 3 ) ) $ "jpg|jpeg"
                  cMimeType = "image/jpeg"
               case Lower( Right( aFiles[ nI ], 3 ) ) == "pdf"
                  cMimeType = "application/pdf"
               case Lower( Right( aFiles[ nI ], 3 ) ) == "txt"
                  cMimeType = "text/plain"
               case Lower( Right( aFiles[ nI ], 3 ) ) == "csv"
                  cMimeType = "text/csv"
               case Lower( Right( aFiles[ nI ], 3 ) ) == "prg"
                  cMimeType = "text/plain"
               case Lower( Right( aFiles[ nI ], 2 ) ) == "ch"
                  cMimeType = "text/plain"
               otherwise
                  if !Empty( cTempFile ) .and. File( cTempFile )
                     hb_FileDelete( cTempFile )
                  endif
                  return "Unsupported file type: " + aFiles[ nI ]
            endcase
            AAdd( aParts, { "fileData" => { "fileUri" => cFileUri, "mimeType" => cMimeType } } )
            if !Empty( cTempFile ) .and. File( cTempFile )
               hb_FileDelete( cTempFile )
            endif
         else
            return "Invalid file in array: " + aFiles[ nI ]
         endif
      next
      lIsFile = .T.
   elseif hb_isChar( uContent ) .and. File( uContent )
      lIsFile = .T.
      cFileNameToUpload = uContent
      cTempFile = nil
      if Lower( Right( uContent, 3 ) ) == "prg"
         cTempFile = hb_FNameMerge( hb_FNameDir( uContent ), hb_FNameName( uContent ), "txt" )
         hb_FCopy( uContent, cTempFile )
         cFileNameToUpload = cTempFile
      elseif Lower( Right( uContent, 2 ) ) == "ch"
         cTempFile = hb_FNameMerge( hb_FNameDir( uContent ), hb_FNameName( uContent ), "txt" )
         hb_FCopy( uContent, cTempFile )
         cFileNameToUpload = cTempFile
      endif
      cFileUri = ::UploadFile( cFileNameToUpload, !Empty( cTempFile ) )
      if Empty( cFileUri )
         if !Empty( cTempFile ) .and. File( cTempFile )
            hb_FileDelete( cTempFile )
         endif
         return ""
      endif
      do case
         case Lower( Right( uContent, 3 ) ) == "png"
            cMimeType = "image/png"
         case Lower( Right( uContent, 3 ) ) $ "jpg|jpeg"
            cMimeType = "image/jpeg"
         case Lower( Right( uContent, 3 ) ) == "pdf"
            cMimeType = "application/pdf"
         case Lower( Right( uContent, 3 ) ) == "txt"
            cMimeType = "text/plain"
         case Lower( Right( uContent, 3 ) ) == "csv"
            cMimeType = "text/csv"
         case Lower( Right( uContent, 3 ) ) == "prg"
            cMimeType = "text/plain"
         case Lower( Right( uContent, 2 ) ) == "ch"
            cMimeType = "text/plain"
         otherwise
            if !Empty( cTempFile ) .and. File( cTempFile )
               hb_FileDelete( cTempFile )
            endif
            return "Unsupported file type"
      endcase
      AAdd( aParts, { "fileData" => { "fileUri" => cFileUri, "mimeType" => cMimeType } } )
      if !Empty( cTempFile ) .and. File( cTempFile )
         hb_FileDelete( cTempFile )
      endif
   endif

   cUrlEndpoint = iif( hb_isBlock( bCallback ), ":streamGenerateContent", ":generateContent" )
   curl_easy_setopt( ::hCurl, HB_CURLOPT_POST, .T. )
   curl_easy_setopt( ::hCurl, HB_CURLOPT_URL, ::cUrl + "/" + ::cModel + cUrlEndpoint + "?key=" + ::cKey )

   aHeaders := { "Content-Type: application/json" }
   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. )

   hContents[ "role" ] = "user"
   if lIsFile
      hRequest[ "contents" ] = { { "role" => "user", "parts" => aParts } }
      if ! Empty( cPrompt )
         AAdd( hRequest[ "contents" ], { "role" => "user", "parts" => { { "text" => cPrompt } } } )
      endif
   else
      hContents[ "parts" ] = { { "text" => iif( hb_isChar( uContent ), uContent, cPrompt ) } }
      hRequest[ "contents" ] = { hContents }
   endif

   hGenerationConfig = { "temperature" => ::nTemperature,;
                         "topK" => 40, "topP" => 0.95, "maxOutputTokens" => 8192,;
                         "responseMimeType" => "text/plain" }
   hRequest[ "generationConfig" ] = hGenerationConfig

   cJson = hb_jsonEncode( hRequest )
   curl_easy_setopt( ::hCurl, HB_CURLOPT_POSTFIELDS, cJson )

   if hb_isBlock( bCallback )
      curl_easy_setopt( ::hCurl, HB_CURLOPT_WRITEFUNCTION, bCallback )
   endif

   ::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 = "CURL Error code " + Str( ::nError )
   endif

return ::cResponse

//----------------------------------------------------------------------------//

METHOD UploadFile( cFileName, lDeleteAfter ) CLASS TGemini

   local pCurl, aPost := {}, hHash

   if hb_isPointer( pCurl := curl_easy_init() )

      curl_easy_setopt( pCurl, HB_CURLOPT_CUSTOMREQUEST, "POST" )
      curl_easy_setopt( pCurl, HB_CURLOPT_URL, ::cUploadUrl + "?key=" + ::cKey )
      curl_easy_setopt( pCurl, HB_CURLOPT_FOLLOWLOCATION, .T. )
      curl_easy_setopt( pCurl, HB_CURLOPT_DL_BUFF_SETUP )
      curl_easy_setopt( pCurl, HB_CURLOPT_SSL_VERIFYPEER, .F. )

      AAdd( aPost, { "file", hb_jsonEncode( { "display_name" => cFileName } ) } )
      AAdd( aPost, { nil, cFileName } )

      curl_easy_setopt( pCurl, HB_CURLOPT_MIMEPOST, aPost )

      if ( ::nError := curl_easy_perform( pCurl ) ) == HB_CURLE_OK
         hHash = hb_jsonDecode( ::cResponse := curl_easy_dl_buff_get( pCurl ) )
      else
         MsgAlert( "curl error: " + AllTrim( Str( ::nError ) ) )
      endif

      curl_easy_cleanup( pCurl )
   endif

   if hb_isHash( hHash )
      #ifndef __XHARBOUR__
         if hb_hHasKey( hHash, "file" ) .and. hb_hHasKey( hHash[ "file" ], "uri" )
      #else
         if HHasKey( hHash, "file" ) .and. HHasKey( hHash[ "file" ], "uri" )      
      #endif      
        return hHash[ "file" ][ "uri" ]
      endif
   endif

   if lDeleteAfter .and. File( cFileName )
      hb_FileDelete( cFileName )
   endif

return ""

//----------------------------------------------------------------------------//

METHOD GetTokens( cBuffer ) CLASS TGemini

   local hResponse, cValue := ""

   if Left( cBuffer, 1 ) == ","
      cBuffer = SubStr( cBuffer, 2 )
   endif

   hb_jsonDecode( cBuffer, @hResponse )

   if ! Empty( hResponse )
      if ValType( hResponse ) == "A"  // Streaming response (array of chunks)
         if hb_hHasKey( hResponse[ 1 ], "error" )
            cValue = "API Error: " + hResponse[ 1 ][ "error" ][ "message" ] + " (Code: " + hb_ntos( hResponse[ 1 ][ "error" ][ "code" ] ) + ")"
         elseif hb_hHasKey( hResponse[ 1 ], "candidates" ) .and. Len( hResponse[ 1 ][ "candidates" ] ) > 0
            TRY
               cValue = hResponse[ 1 ][ "candidates" ][ 1 ][ "content" ][ "parts" ][ 1 ][ "text" ]
            CATCH
               cValue = "Error: Unexpected streaming response structure"
            END
         else
            cValue = "Error: No candidates in streaming response"
         endif
      elseif hb_isHash( hResponse )  // Non-streaming response
         if hb_hHasKey( hResponse, "error" )
            cValue = "API Error: " + hResponse[ "error" ][ "message" ] + " (Code: " + hb_ntos( hResponse[ "error" ][ "code" ] ) + ")"
         elseif hb_hHasKey( hResponse, "candidates" ) .and. Len( hResponse[ "candidates" ] ) > 0
            TRY
               cValue = hResponse[ "candidates" ][ 1 ][ "content" ][ "parts" ][ 1 ][ "text" ]
            CATCH
               cValue = "Error: Unexpected response structure"
            END
         else
            cValue = "Error: No candidates in response"
         endif
      else
         cValue = "Error: Invalid response format in streaming buffer"
      endif
   endif

return cValue

//----------------------------------------------------------------------------//

#ifdef __XHARBOUR__
   
function HB_FNAMEDIR( cFileName )
   local nLastSlash := Max( RAt( "\", cFileName ), RAt( "/", cFileName ) )
   if nLastSlash > 0
      return Left( cFileName, nLastSlash )
   endif
return ""

function HB_FNAMENAME( cFileName )
   local cName := cFileName
   local nLastSlash := Max( RAt( "\", cFileName ), RAt( "/", cFileName ) )
   local nLastDot

   if nLastSlash > 0
      cName = SubStr( cFileName, nLastSlash + 1 )
   endif

   nLastDot = RAt( ".", cName )
   if nLastDot > 0
      cName = Left( cName, nLastDot - 1 )
   endif

return cName

function HB_FCOPY( cSource, cDest )

   local hSource, hDest, nBytes, nRead, aBuffer := {}

   if hb_isPointer( hSource := FOpen( cSource, "rb" ) )
      if hb_isPointer( hDest := FOpen( cDest, "wb" ) )
         while ! hb_feof( hSource )
            nRead := FRead( aBuffer, 1, 1024, hSource )
            FWrite( aBuffer, 1, nRead, hDest )
         end
         FClose( hDest )
      endif
      FClose( hSource )
   endif

return nil   

function HB_FILEDELETE( cFileName )

   if File( cFileName )
      return FErase( cFileName )
   endif

return nil

#endif
regards, saludos

Antonio Linares
www.fivetechsoft.com
Enrrique Vertiz
Posts: 554
Joined: Fri Oct 07, 2005 2:17 pm
Location: Lima - Peru
Been thanked: 3 times
Contact:

Re: Error al compilar ejemplos Gemini# con xHb

Post by Enrrique Vertiz »

Saludos Antonio

Copie el codigo y lo grabe como tgemini.prg en la carpeta clases, lo aumente en el Buildx.bat y ahora me sale el siguiente error

Image
Enrrique Vertiz Pitta
Lima-Peru
xHb 1.23.1026X, Fwh 24.09, BCC74, MySQL 8.0.X, SQLLIB 1.9m
User avatar
Antonio Linares
Site Admin
Posts: 42575
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Has thanked: 36 times
Been thanked: 84 times
Contact:

Re: Error al compilar ejemplos Gemini# con xHb

Post by Antonio Linares »

Enrique,

Vamos a distribuir un build actualizado de FWH 25.01

El error que te sale es porque está intentando usar el PRG como si fuese un OBJ

gracias!
regards, saludos

Antonio Linares
www.fivetechsoft.com
Post Reply