Page 4 of 5

Re: Webview 2 + Html + ChatGPT !

Posted: Fri Sep 27, 2024 6:44 am
by Antonio Linares

Re: Webview 2 + Html + ChatGPT !

Posted: Fri Sep 27, 2024 8:40 am
by Antonio Linares
Comenzando a implementar la carga de apps previamente salvadas a DBF:

buildit.prg

Code: Select all | Expand

#include "FiveWin.ch"

REQUEST DbfCdx
// REQUEST HB_CODEPAGE_ESWIN
// REQUEST HB_LANG_ESWIN

// get your OpenAI key from https://platform.openai.com/api-keys
static cKey := "sk-proj-..."  
static oChatgpt
static oTree
static cCategory := "                              "
static oWebView
static cContext := "                                                                   "
static oExplBar, oExplPanel

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

function Main()

   local oWnd, oAppPanel

   oChatgpt = TChatgpt():New( cKey )

   DEFINE WINDOW oWnd TITLE "Build it"

   oExplBar = TExplorerBar():New( 0, 82, 480, 100, oWnd:oLeft, CLR_WHITE, RGB( 31, 31, 31 ) )
   oWnd:oLeft = oExplBar

   oExplPanel = oExplBar:AddPanel( "AI assistant" )
   oExplPanel:AddLink( "what is this app about ?",;
                       { || If( MsgGet( "App category", "Please specify it", @cCategory ), AddOptions( cCategory, oExplBar ),) } )
   oExplPanel:AddLink( "Add options to selected item", { || AddSubOptions() } )
   oExplPanel:AddLink( "Generate HTML for selected item", { || MsgRun( "Building the GUI", "Please wait", { || GenerateHTML() } ) } )
   oExplPanel:AddLink( "Modify HTML for selected item", { || ModifyHTML() } )
   oExplPanel:AddLink( "Overall context", { || Context() } ) 
   oExplPanel:AddLink( "Save App", { || SaveApp() } )
   oExplPanel:AddLink( "Load App", { || LoadApp() } )

   oWnd:oClient = TPanel():New( 0, 0, 100, 100, oWnd )

   oWebView = TWebView2():New( oWnd:oClient )
   oWebView:Navigate( "https://www.google.com" )

   ACTIVATE WINDOW oWnd MAXIMIZED ;
      ON RESIZE ( oWebView:SetSize( nWidth - oExplBar:nWidth, nHeight ), oExplBar:SetSize( 480, nHeight ) )

return nil    

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

function AddOptions( cCategory, oExplBar )

   local cOptions, aOptions, cOption, oAppPanel, oItem

   oChatgpt:cPrompt := "genera una lista separada por comas con las opciones de una aplicación de " + ;
                       hb_StrToUtf8( AllTrim( cCategory ) ) + ". No des ninguna explicación"
   MsgRun( "Asking ChatGPT", "Please wait", { || oChatgpt:Send() } ) 

   cOptions = oChatgpt:GetValue( "choices", "message", "content" )
   aOptions = hb_ATokens( cOptions, "," )

   oAppPanel = oExplBar:AddPanel( cCategory,, 700 )
   cCategory = hb_Utf8ToStr( AllTrim( cCategory ) )
   oTree = TTreeView():New( 2.5, 2, oAppPanel,,,,, 423, 675 )
   oTree:bChanged = { || oItem := oTree:GetSelected(), oWebView:SetHtml( If( ! Empty( oItem:Cargo ), oItem:Cargo, "" ) ) }

   for each cOption in aOptions 
      oItem = oTree:Add( cOption )
      oItem:Cargo = HtmlDefault()
   next   
    
return nil    

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

function AddSubOptions()

   local oItem 
   local cOption := If( ( oItem := oTree:GetSelected() ) != nil, oItem:cPrompt, "" ) 
   local cOptions, cSubOption, aOptions, oSubItem

   if ! Empty( cOption )
      oChatgpt:cPrompt := "genera una lista separada por comas con las opciones de " + hb_StrToUtf8( cOption ) + ;
                          " para una aplicación de " + hb_StrToUtf8( cCategory ) + ". No des ninguna explicación"
      MsgRun( "Asking ChatGPT", "Please wait", { || oChatgpt:Send() } )

      cOptions = oChatgpt:GetValue( "choices", "message", "content" )
      aOptions = hb_ATokens( cOptions, "," )

      for each cSubOption in aOptions 
         oSubItem = oItem:Add( cSubOption )
         oSubItem:Cargo = HtmlDefault()
      next   

      oItem:Expand()
   endif   

return nil    

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

function GenerateHTML()

   local oItem, cHTML 
   local cOption := If( ( oItem := oTree:GetSelected() ) != nil, oItem:cPrompt, "" ) 

   if ! Empty( cOption )
      oChatgpt:cPrompt := "genera el código HTML usando bootstrap para la opción " + hb_StrToUtf8( cOption ) + ;
                          " para una aplicación de " + hb_StrToUtf8( AllTrim( cCategory ) ) + ;
                          ". Que se vea muy profesional y elegante. No des ninguna explicación. " + ;
                          cContext 
      oChatgpt:Send()
      cHTML = oChatgpt:GetValue( "choices", "message", "content" )
      oItem:Cargo = SubStr( cHTML, 8, Len( cHTML ) - 10 )
      oWebView:SetHTML( oItem:Cargo )
   endif   

return nil   

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

function ModifyHTML()

   local oItem, cHTML 
   local cOption := If( ( oItem := oTree:GetSelected() ) != nil, oItem:cPrompt, "" ) 
   local cChange := Space( 50 )

   if fw_memoEdit( @cChange, "What do you want to change ?" )
      cChange = AllTrim( cChange )
   endif      

   if ! Empty( cOption )
      oChatgpt:cPrompt := "modifica este código HTML usando bootstrap para la opción " + hb_StrToUtf8( cOption ) + ;
                          " para una aplicación de " + hb_StrToUtf8( AllTrim( cCategory ) ) + ;
                          ". Que se vea muy profesional y elegante. No des ninguna explicación. " + ;
                          cContext + ". Y aplica _ exactamente: " + hb_StrToUtf8( cChange ) + ;
                          oItem:Cargo 
      MsgRun( "Asking ChatGPT", "Please wait", { || oChatgpt:Send() } ) 
      cHTML = oChatgpt:GetValue( "choices", "message", "content" )
      oItem:Cargo = SubStr( cHTML, 8, Len( cHTML ) - 10 )
      oWebView:SetHTML( oItem:Cargo )
   endif   

return nil   

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

function Context()

   if fw_memoEdit( @cContext, "Overall context for HTML generation" )
      cContext = AllTrim( cContext )
   endif      

return nil   

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

function CreateDBF( cFileName )

   DbCreate( cFileName + ".dbf", { { "prompt", "C", 80, 0 },;
                                   { "level",  "N",  3, 0 },;
                                   { "html",   "M", 10, 0 } }, "DBFCDX" )
   USE ( cFileName )

return nil

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

function SaveApp()

   if ! File( cCategory + ".dbf" )
      CreateDBF( StrTran( AllTrim( cCategory ), " ", "_" ) )
   else
      if MsgYesNo ("App already exists", "Do you want to overwrite it?" )
         CreateDBF( StrTran( AllTrim( cCategory ), " ", "_" ) )
      else
         return nil
      endif
   endif

   oTree:Scan( { | oItem, nPos, nLevel | DbAppend(), field->prompt := oItem:cPrompt,;
               field->level := nLevel, field->html := oItem:Cargo, .F. } )
   GO TOP
   XBrowse()
   USE

return nil   

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

function LoadApp()

   local cFileName := cGetFile( "DBF file| *.dbf", "Please select a DBF" )
   local oAppPanel, oItem, oLastItem, nLevel := 1, aLevels := {}

   USE ( cFileName )

   oAppPanel = oExplBar:AddPanel( cFileNoExt( cFileName ),, 700 )
   oTree = TTreeView():New( 2.5, 2, oAppPanel,,,,, 423, 675 )

   while ! EoF()
      IF field->level > nLevel
         // Aumenta el nivel, guarda el elemento actual y crea una nueva rama
         AADD(aLevels, oLastItem)
         nLevel++
         oItem := oLastItem:Add(field->prompt)
         oLastItem := oItem
      ELSEIF field->level < nLevel
         // Disminuye el nivel, recupera el elemento del nivel anterior
         WHILE nLevel > field->level .AND. !EMPTY(aLevels)
            nLevel--
            oLastItem := ATAIL(aLevels)
            ADEL(aLevels, LEN(aLevels))
         ENDDO
         if oLastItem != nil
            oItem := oLastItem:Add( field->prompt )
         endif   
      ELSE
         // Mismo nivel, añade un nuevo elemento al nivel actual
         oItem := oTree:Add( field->prompt )
         oLastItem := oItem
      ENDIF
   
      oItem:Cargo := field->html
      SKIP
   end  

   USE

return nil   

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

function HtmlDefault()

   local cHtml

   TEXT INTO cHtml
      <!DOCTYPE html>
      <html lang="es">
      <head>
         <style>
            body {
                  background-color: rgb(31, 31, 31);
            }
         </style>
      </head>
      <body>
      </body>
      </html>
   ENDTEXT 

return cHtml

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

Re: Webview 2 + Html + ChatGPT !

Posted: Fri Sep 27, 2024 2:54 pm
by cmsoft
Antonio:
Donde puedo descargar habour completo
Ya que el path %hdir%\bin\win\bcc\harbour no existe

Re: Webview 2 + Html + ChatGPT !

Posted: Fri Sep 27, 2024 3:11 pm
by Enrrique Vertiz
Saludos Antonio

Entiendo que al tener cambio FWH, no podemos compilar los ejemplos que aqui estas colocando, pero indicas que pasaras un EXE, me dices x favor de donde descargarlo para empezar a probar y donde coloco mi Key de OpenIA para probarlo
Gracias

Re: Webview 2 + Html + ChatGPT !

Posted: Fri Sep 27, 2024 4:04 pm
by wilsongamboa
buenos dias con todos a mi si me compila pero no puedo probar porque
1.- no se de que se trata ??
2.- no tengo ese chatgpt o esa suscripcion

alguna alma caritativa que pueda explicarnos de que se trata
hacer un programa con webview ?? y chtgpt ?
saludospd: perdon la ignorancia

Re: Webview 2 + Html + ChatGPT !

Posted: Fri Sep 27, 2024 4:14 pm
by cmsoft
Wilson:
La idea es tener integrado OpenIA con Fivewin.
En conjuto con WebView para mostrar el resultado html de lo que se le solicita a la IA para ver como va respondiendo .
Para esto, además del programa que muestra Antonio, hay que registrarse en OpenIA (https://platform.openai.com/) para obtener una Key de la API
Es muy interesante lo que está desarrollando Antonio con todo esto.

Re: Webview 2 + Html + ChatGPT !

Posted: Fri Sep 27, 2024 4:17 pm
by wilsongamboa
Cesar muchas gracias la info ahi me aclara
esa suscripcion es de pago ?
saludos

Re: Webview 2 + Html + ChatGPT !

Posted: Fri Sep 27, 2024 4:28 pm
by wilsongamboa
perdon ya averigue son 20 dolares por mes
saludos

Re: Webview 2 + Html + ChatGPT !

Posted: Fri Sep 27, 2024 4:29 pm
by wilsongamboa
y la gratuita no tiene acceso a la API

Re: Webview 2 + Html + ChatGPT !

Posted: Fri Sep 27, 2024 4:32 pm
by cmsoft
Si, es de pago... Lamentablemente.

Re: Webview 2 + Html + ChatGPT !

Posted: Fri Sep 27, 2024 4:39 pm
by wilsongamboa
gracias Cesar veamos hasta donde se llega con esto y evaluamos usarlo tambien
saludos

Re: Webview 2 + Html + ChatGPT !

Posted: Sat Sep 28, 2024 6:27 am
by Antonio Linares
wilsongamboa wrote:perdon ya averigue son 20 dolares por mes
saludos
No, ese precio es para la versión plus. El precio es menos de un dolar!

Solo teneis que proporcionar los datos de pago en OpenAI. La version gpt-4o-mini que usamos es muy muy barata.

Daros de alta, realmente merece la pena y los resultados son espectaculares!

Re: Webview 2 + Html + ChatGPT !

Posted: Sat Sep 28, 2024 6:29 am
by Antonio Linares
cmsoft wrote:Antonio:
Donde puedo descargar habour completo
Ya que el path %hdir%\bin\win\bcc\harbour no existe
https://github.com/FiveTechSoft/harbour ... 240814.zip

Re: Webview 2 + Html + ChatGPT !

Posted: Sat Sep 28, 2024 6:43 am
by Antonio Linares
Estamos construyendo un generador/prototipador de aplicaciones usando Inteligencia Artificial y Harbour + FWH

Os recomiendo probarlo, es simplemente espectacular! :-)

Y las posibilidades son enormes!

Re: Webview 2 + Html + ChatGPT !

Posted: Sun Sep 29, 2024 9:32 pm
by Antonio Linares
Carga de la aplicación funcionando correctamente:

buildit.prg

Code: Select all | Expand

#include "FiveWin.ch"

REQUEST DbfCdx
// REQUEST HB_CODEPAGE_ESWIN
// REQUEST HB_LANG_ESWIN

// get your OpenAI key from https://platform.openai.com/api-keys
static cKey := "sk-proj-..."  
static oChatgpt
static oTree
static cCategory := "                              "
static oWebView
static cContext := "                                                                   "
static oExplBar, oExplPanel

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

function Main()

   local oWnd, oAppPanel

   oChatgpt = TChatgpt():New( cKey )

   DEFINE WINDOW oWnd TITLE "Build it"

   oExplBar = TExplorerBar():New( 0, 82, 480, 100, oWnd:oLeft, CLR_WHITE, RGB( 31, 31, 31 ) )
   oWnd:oLeft = oExplBar

   oExplPanel = oExplBar:AddPanel( "AI assistant" )
   oExplPanel:AddLink( "what is this app about ?",;
                       { || If( MsgGet( "App category", "Please specify it", @cCategory ), AddOptions( cCategory, oExplBar ),) } )
   oExplPanel:AddLink( "Add options to selected item", { || AddSubOptions() } )
   oExplPanel:AddLink( "Generate HTML for selected item", { || MsgRun( "Building the GUI", "Please wait", { || GenerateHTML() } ) } )
   oExplPanel:AddLink( "Modify HTML for selected item", { || ModifyHTML() } )
   oExplPanel:AddLink( "Overall context", { || Context() } )
   oExplPanel:AddLink( "Save App", { || SaveApp() } )
   oExplPanel:AddLink( "Load App", { || LoadApp() } )

   oWnd:oClient = TPanel():New( 0, 0, 100, 100, oWnd )

   oWebView = TWebView2():New( oWnd:oClient )
   oWebView:Navigate( "https://www.google.com" )

   ACTIVATE WINDOW oWnd MAXIMIZED ;
      ON RESIZE ( oWebView:SetSize( nWidth - oExplBar:nWidth, nHeight ), oExplBar:SetSize( 480, nHeight ) )

return nil    

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

function AddOptions( cCategory, oExplBar )

   local cOptions, aOptions, cOption, oAppPanel, oItem

   oChatgpt:cPrompt := "genera una lista separada por comas con las opciones de una aplicación de " + ;
                       hb_StrToUtf8( AllTrim( cCategory ) ) + ". No des ninguna explicación"
   MsgRun( "Asking ChatGPT", "Please wait", { || oChatgpt:Send() } )

   cOptions = oChatgpt:GetValue( "choices", "message", "content" )
   aOptions = hb_ATokens( cOptions, "," )

   oAppPanel = oExplBar:AddPanel( cCategory,, 700 )
   cCategory = hb_Utf8ToStr( AllTrim( cCategory ) )
   oTree = TTreeView():New( 2.5, 2, oAppPanel,,,,, 423, 675 )
   oTree:bChanged = { || oItem := oTree:GetSelected(), oWebView:SetHtml( If( ! Empty( oItem:Cargo ), oItem:Cargo, "" ) ) }

   for each cOption in aOptions
      oItem = oTree:Add( cOption )
      oItem:Cargo = HtmlDefault()
   next  
   
return nil    

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

function AddSubOptions()

   local oItem
   local cOption := If( ( oItem := oTree:GetSelected() ) != nil, oItem:cPrompt, "" )
   local cOptions, cSubOption, aOptions, oSubItem

   if ! Empty( cOption )
      oChatgpt:cPrompt := "genera una lista separada por comas con las opciones de " + hb_StrToUtf8( cOption ) + ;
                          " para una aplicación de " + hb_StrToUtf8( cCategory ) + ". No des ninguna explicación"
      MsgRun( "Asking ChatGPT", "Please wait", { || oChatgpt:Send() } )

      cOptions = oChatgpt:GetValue( "choices", "message", "content" )
      aOptions = hb_ATokens( cOptions, "," )

      for each cSubOption in aOptions
         oSubItem = oItem:Add( cSubOption )
         oSubItem:Cargo = HtmlDefault()
      next  

      oItem:Expand()
   endif  

return nil    

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

function GenerateHTML()

   local oItem, cHTML
   local cOption := If( ( oItem := oTree:GetSelected() ) != nil, oItem:cPrompt, "" )

   if ! Empty( cOption )
      oChatgpt:cPrompt := "genera el código HTML usando bootstrap para la opción " + hb_StrToUtf8( cOption ) + ;
                          " para una aplicación de " + hb_StrToUtf8( AllTrim( cCategory ) ) + ;
                          ". Que se vea muy profesional y elegante. No des ninguna explicación. " + ;
                          cContext
      oChatgpt:Send()
      cHTML = oChatgpt:GetValue( "choices", "message", "content" )
      oItem:Cargo = SubStr( cHTML, 8, Len( cHTML ) - 10 )
      oWebView:SetHTML( oItem:Cargo )
   endif  

return nil  

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

function ModifyHTML()

   local oItem, cHTML
   local cOption := If( ( oItem := oTree:GetSelected() ) != nil, oItem:cPrompt, "" )
   local cChange := Space( 50 )

   if fw_memoEdit( @cChange, "What do you want to change ?" )
      cChange = AllTrim( cChange )
   endif      

   if ! Empty( cOption )
      oChatgpt:cPrompt := "modifica este código HTML usando bootstrap para la opción " + hb_StrToUtf8( cOption ) + ;
                          " para una aplicación de " + hb_StrToUtf8( AllTrim( cCategory ) ) + ;
                          ". Que se vea muy profesional y elegante. No des ninguna explicación. " + ;
                          cContext + ". Y aplica _ exactamente: " + hb_StrToUtf8( cChange ) + ;
                          oItem:Cargo
      MsgRun( "Asking ChatGPT", "Please wait", { || oChatgpt:Send() } )
      cHTML = oChatgpt:GetValue( "choices", "message", "content" )
      oItem:Cargo = SubStr( cHTML, 8, Len( cHTML ) - 10 )
      oWebView:SetHTML( oItem:Cargo )
   endif  

return nil  

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

function Context()

   if fw_memoEdit( @cContext, "Overall context for HTML generation" )
      cContext = AllTrim( cContext )
   endif      

return nil  

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

function CreateDBF( cFileName )

   DbCreate( cFileName + ".dbf", { { "prompt", "C", 80, 0 },;
                                   { "level",  "N",  3, 0 },;
                                   { "html",   "M", 10, 0 } }, "DBFCDX" )
   USE ( cFileName )

return nil

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

function SaveApp()

   if ! File( cCategory + ".dbf" )
      CreateDBF( StrTran( AllTrim( cCategory ), " ", "_" ) )
   else
      if MsgYesNo ("App already exists", "Do you want to overwrite it?" )
         CreateDBF( StrTran( AllTrim( cCategory ), " ", "_" ) )
      else
         return nil
      endif
   endif

   oTree:Scan( { | oItem, nPos, nLevel | DbAppend(), field->prompt := oItem:cPrompt,;
               field->level := nLevel, field->html := oItem:Cargo, .F. } )
   GO TOP
   XBrowse()
   USE

return nil  

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

function LoadApp()

   local cFileName := cGetFile( "DBF file| *.dbf", "Please select a DBF" )
   local oAppPanel, oItem, oLastItem, nLevel := 1, aLevels := {}

   if Empty( cFileName )
      return nil 
   endif   

   cCategory = cFileNoExt( cFileName )
   USE ( cFileName )

   oAppPanel = oExplBar:AddPanel( cFileNoExt( cFileName ),, 700 )
   oTree = TTreeView():New( 2.5, 2, oAppPanel,,,,, 423, 675 )
   oTree:bChanged = { || oItem := oTree:GetSelected(), oWebView:SetHtml( If( ! Empty( oItem:Cargo ), oItem:Cargo, "" ) ) }

   while ! EoF()
      do case
         case field->level > nLevel
            nLevel = field->level
            oItem = oLastItem:Add( field->prompt )
            oLastItem = oItem
            AAdd( aLevels, oLastItem )

         case field->level < nLevel
            oLastItem = ATail( aLevels )
            aLevels = ASize( aLevels, Len( aLevels ) - 1 )
            nLevel = field->level
            if nLevel == 1
               oItem = oTree:Add( field->prompt )
            else   
               oItem = oLastItem:oParent:Add( field->prompt )
            endif   
            oLastItem = oItem

         case field->level == nLevel  
            if nLevel == 1
               oItem = oTree:Add( field->prompt )
            else 
               oItem = oLastItem:oParent:Add( field->prompt )  
            endif      
            oLastItem = oItem
      endcase
   
      oItem:Cargo = field->html
      SKIP
   end  

   USE

return nil  

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

function HtmlDefault()

   local cHtml

   TEXT INTO cHtml
      <!DOCTYPE html>
      <html lang="es">
      <head>
         <style>
            body {
                  background-color: rgb(31, 31, 31);
            }
         </style>
      </head>
      <body>
      </body>
      </html>
   ENDTEXT

return cHtml

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