THFTask & TChatAgent - FWAI utilities
Source: source/classes/thftask.prg, source/classes/tchatagent.prg
Two "FWAI" utility classes that bring everyday AI tasks into FiveWin apps with a few lines — see the PyTorch-lite roadmap.
THFTask — HuggingFace NLP tasks
One thin class over the HuggingFace Inference API for the common NLP tasks. Each method posts to the right model endpoint and returns plain Harbour values.
| Method | Returns |
|---|---|
Classify( cText [,cModel] ) | { {label,score}, ... } descending |
ZeroShot( cText, aLabels [,cModel] ) | { {label,score}, ... } for your own labels |
NER( cText [,cModel] ) | { {entity,word,score}, ... } |
Summarize( cText [,cModel] ) | summary string |
Translate( cText [,cModel] ) | translation string (en→es by default) |
Sentiment( cText [,cModel] ) | { label, score } (top) |
oT := THFTask():New() // uses HF_API_KEY
aCls := oT:Classify( "win a free prize now" ) // -> { {"spam",0.91}, {"ham",0.09} }
? oT:Summarize( cLongReport )
? oT:Translate( "Hello world" ) // "Hola mundo"
aEnt := oT:NER( "John lives in Madrid" ) // PER John, LOC Madrid
aZ := oT:ZeroShot( "my invoice is wrong", { "billing", "tech" } )
The transport is injectable via ::bSender { |cUrl, cJson| -> cResponseJson }
— leave it NIL to use libcurl, or set it to mock responses (the test
samples/ai/thftasktest.prg verifies parsing offline) or route through a
different HTTP layer / a local server.
TChatAgent — chat over your app's data
A minimal agent with tool-calling: the LLM either answers, or asks the app to run a query; the app returns rows and the loop continues until the LLM answers. Backend-agnostic via two codeblocks.
| Method | Description |
|---|---|
New( bChat, bTool [,cSystem] ) | bChat = { |cPrompt| -> cReply } (LLM, e.g. TOLlama or an API class); bTool = { |cQuery| -> cResultText } (you run the DBF/SQL query). |
Ask( cQuestion ) | Run the loop and return the final answer text. |
oLlm := TOLlama():New( "llama3" )
oAgent := TChatAgent():New( ;
{ |cPrompt| oLlm:Send( cPrompt ), oLlm:GetValue() }, ; // LLM backend
{ |cQuery| RunMyQuery( cQuery ) } ) // your data tool
? oAgent:Ask( "how many overdue invoices this month?" )
The LLM is instructed to reply either TOOL <query> or
ANSWER <text>; tool results are fed back as
RESULT: <rows> until it answers (or nMaxSteps).
Pair it with TSemanticIndex to let the
agent retrieve relevant records. Test: samples/ai/chatagenttest.prg.
TWhisperCpp — offline speech-to-text
Local, private speech-to-text via whisper.cpp (MIT, free). No API, no cost, no data leaving the machine — great for dictation into GETs or transcribing voice notes.
oW := TWhisperCpp():New( "ggml-base.bin" )
if oW:IsAvailable()
cText := oW:Transcribe( "note.wav" ) // 16 kHz mono PCM WAV
endif
oW:End()
Optional, zero-cost for everyone else. The class lives in the FWH
library, but the native binding (source/winapi/whispercpp.c) is
not part of the FWH C library and is never linked by default — normal
apps link nothing extra and IsAvailable() simply returns .F..
An app that wants speech-to-text builds whisper.cpp as a static lib and compiles
that one file into its own build with -DHB_HAS_WHISPER + libwhisper.
Models (ggml-tiny/base/small...) are free from huggingface.co/ggerganov/whisper.cpp.
Demo: samples/ai/whisperdemo.prg; degradation test:
samples/ai/whispertest.prg.