Poskytněte umělou inteligenci 30 let staré aplikaci 4D

Automaticky přeloženo z Deepl

Během několika let se umělá inteligence změnila z nově vznikajícího trendu na nezbytnou součást moderního softwaru. ChatGPT, Grok, Gemini a další asistenti s umělou inteligencí dnes hrají významnou roli v každodenním životě každého člověka, a to jak v profesním, tak v osobním životě.
Proto společnost 4D 21 představuje 4D.Vectors a 4D AI Kit: aby vývojáři 4D měli k dispozici jednoduché a účinné nástroje pro přidávání funkcí poháněných umělou inteligencí do svých aplikací.
O AI jsme již sdíleli mnoho příkladů, tutoriálů a webinářů, ale nedávno jsem si položil otázku: Co by bylo potřeba udělat, aby se AI dostala do 30 let staré aplikace 4D?
Mohli byste se takové aplikace jednoduše zeptat na svých 10 nejlepších zákazníků a okamžitě dostat zpět pěkný graf?

No, hádejte co? Ukázalo se, že je to tak jednoduché, že si to zaslouží vlastní příspěvek na blogu.

Začněme odkazem na zdrojové kódy projektu na Githubu a krátkým ukázkovým videem

Zdroje projektu

 

Aplikace 4D Invoice

Aplikace 4D Invoice je již delší dobu k dispozici v 4D Depotu. Slouží jako solidní příklad toho, jak přehledně a strukturovaně spravovat produkty, zákazníky a faktury. Ačkoli již používá projektový režim (což je podmínka pro využití nejnovějších funkcí 4D AI), nevyužívá ještě třídy DataClasses a její formuláře jsou starší než novější třída Form. Kódová základna je poměrně rozsáhlá, používá obecné návrhové vzory a obsahuje několik netriviálních obchodních pravidel.

V rámci tohoto experimentu bylo mým cílem přidat nový formulář umožňující interakci s aplikací na bázi umělé inteligence. Chtěl jsem, aby uživatelé mohli komunikovat s asistentem AI a pokládat mu cokoli od jednoduchých otázek až po složitější analytické dotazy. V reálném použití by to okamžitě dodalo poněkud „staromódní“ aplikaci moderní ráz, sladěný s dnešními očekáváními uživatelů řízených umělou inteligencí. Vskutku vzrušující!

Dalším cílem bylo vyhnout se jakýmkoli změnám ve struktuře dat a neměnit stávající mechanismy uživatelského rozhraní. Jinými slovy, upgrade AI musel být vysoce flexibilní, minimálně rušivý a v ideálním případě znovu použitelný v jiných starších aplikacích.

V důsledku toho se tento upgrade nespoléhá na 4D.Vectors nebo embeddings. K tomuto tématu se vrátíme později, ale stojí za to ho zdůraznit již nyní: zavedení AI do aplikace 4D nevyžaduje nutně embeddingy nebo sémantické vyhledávání. Jedná se o samostatné koncepty.

Příprava

Ve 4D jsme již sdíleli několik příkladů a webových seminářů založených na AI, včetně nedávných ukázek budování systému RAG pomocí volání nástrojů. Pro tento projekt jsem se rozhodl vyjmout formulář uživatelského rozhraní chatu z ukázkyPeople & Skills a vytvořit jej obecnější a opakovaně použitelný.

Uživatelské rozhraní chatu se skládá z následujících komponent:

  • Formulář AIChat spolu s jeho formulářovou třídou formAIChat.4dm. Tento formulář poskytuje:
    • jednoduchý textový vstup pro výzvu uživatele
    • webovou oblast, která zobrazuje konverzaci s modelem
  • Třídu AI_ChatWithTools, která je zodpovědná za:
    • instanci bota umělé inteligence pomocí pomocného chatu sady 4D AI Kit na základě inferenčního serveru a modelu nakonfigurovaného v souboru Resources/AIProvider.json
    • načtení nástrojů definovaných v souboru Resources/AITools.json
    • hostování implementace těchto nástrojů

Třída běží výhradně v režimu streamování, takže uživatel získá zážitek podobný ChatGPT, přičemž odpovědi se objevují postupně.

  • Ovykreslování konverzací se stará singleton ChatHTMLRenderer.

Ten přebírá kolekci zpráv uložených v AIBotu a převádí je do HTML pomocí šablon umístěných ve složce Resources:

    • chat-template.html
    • chat-template.css
    • tool-icon.svg

 

Budu upřímný: vykreslování HTML bylo v podstatě „vibe-coded“ s pomocí agenta GitHub VS Code a Claude Sonnet 4.5. Nejnáročnější bylo zajistit správné vykreslování během streamování, zejména u prvků, jako jsou tabulky, volání nástrojů a grafy.

Volání nástrojů AI

Jak pravděpodobně víte, model AI ze své podstaty neví nic o vašich datech. Získává k nim přístup pouze prostřednictvím nástrojů, které mu explicitně poskytnete. V této části vysvětlím, které nástroje jsem implementoval a jak fungují.

tool_getProducts, tool_getClients, tool_getInvoices, tool_getInvoiceLines.

Všechny tyto nástroje jsou zodpovědné za dotazování do databáze. Každý z nich provádí jednoduchý dotaz ORDA na základě polí požadovaných modelem.

Samozřejmě existuje rozsáhlý prostor pro vylepšení funkcí těchto nástrojů. Díky nativním funkcím 4D 21 AI bychom si mohli představit sémantické vyhledávání pomocí 4D.Vector a embeddingů pro zvýšení vyhledávání klientů. Protože by to znamenalo hlubší změny v rámci struktury, zvolil jsem jednodušší cestu.

Rozebereme si nástroj_getClients, protože stejný vzorec platí pro všechny ostatní „getter“ nástroje:

Function tool_getClients($input : Object) : Object

Tato funkce přijímá objekt jako vstup a vrací objekt jako výstup. Vstup popisuje parametry vyhledávání; výstup obsahuje výsledná data.

Ověření vstupu

var $validation; $returnObject : Object	
var $entities : cs.CLIENTSSelection:=ds.CLIENTS.all()

$validation:=JSON Validate($input; This._getToolArgumentsSchema(This._functionName(Call chain)))
If (Not($validation.success))
	return {error: "Could not validate input parameters against JSON Schema, call the tool again with proper input parameters"}
End if 

Prvním krokem je ověření, zda vstup odpovídá schématu definovanému v souboru AITools.json.

Většina moderních modelů bude vytvářet dobře strukturovaná volání nástrojů, ale v závislosti na modelu je validace stále dobrou bezpečnostní praxí.

Pokud validace selže, nástroj vrátí jednoduchý objekt obsahující chybovou vlastnost. Je důležité vědět, že model tuto hodnotu čte, takže se nebojte explicitně uvést, co se pokazilo.

Nastavení výchozích vstupních hodnot

$input.ID:=($input.ID) || "any"
$input.Name:=($input.Name) || "@"
$input.Contact:=($input.Contact) || "@"
$input.Total_Sales:=$input.Total_Sales || {}
$input.Total_Sales.min:=$input.Total_Sales.min || 0
$input.Total_Sales.max:=$input.Total_Sales.max || 9999999
$input.orderBy:=($input.orderBy) || {}
$input.orderBy.field:=($input.orderBy.field) || "Name"
$input.orderBy.order:=($input.orderBy.order) || "asc"
$input.top:=($input.top) || This.defaultTop
$input.countOnly:=($input.countOnly) || False

Výchozí hodnoty zajišťují bezpečné dotazy ORDA, ale mají také zajímavou vedlejší výhodu: zápis celého schématu JSON v souboru AITools.json může být zdlouhavý. Místo toho jsem nechal GitHub Copilot odvodit schéma z kódu a výchozí struktury a výsledek byl vynikající. Copilot vytvořil přesnou definici schématu pouze na základě výše uvedené logiky.

Parametry, které je třeba vzít na vědomí

  • orderBy a top snižují velikost výstupu (a tím i spotřebu tokenů).
  • CountOnly umožňuje modelu požadovat pouze počty záznamů bez načítání dat.

 

Praktické příklady:

  • Pokud model potřebuje počet klientů → countOnly = true
  • Pokud chce 5 nejlepších klientů → top = 5 a orderBy: {field: „Total_Sales“, order: „desc“}

 

Inicializace výstupního objektu

$returnObject:={}
$returnObject.form:="Clients"
$returnObject.dataClass:="CLIENTS"
$returnObject.counts:={}
$returnObject.counts.total:=$entities.length
  • Formulář určuje, který formulář uživatelského rozhraní lze použít k zobrazení výsledků – to uvidíme později.
  • dataClass identifikuje příslušnou datovou třídu, což je důležité pro dotazování napříč několika tabulkami – to uvidíme také později.
  • counts.total je počet záznamů před použitím jakéhokoli filtru.

 

Provedení dotazu

If ($input.ID#"any")
	$entities:=$entities.query("ID = :1"; $input.ID)
End if 

$entities:=$entities.query("Name = :1 and Contact = :2 and Total_Sales >= :3 and Total_Sales <= :4 order by "+$input.orderBy.field+" "+$input.orderBy.order; $input.Name; $input.Contact; $input.Total_Sales.min; $input.Total_Sales.max)

Tato část je přímočará a jistě by mohla být obecnější, ale na to jsem se zde nezaměřoval.

Dokončení výsledku

$returnObject.counts.totalFiltered:=$entities.length
If ($returnObject.counts.totalFiltered>$input.top)
	$entities:=$entities.slice(0; $input.top)
End if 

$returnObject.counts.totalSent:=$entities.length
$returnObject.entities:=($input.countOnly) ? [] : $entities.toCollection("ID, Name, Contact, City, State, Country, Discount_Rate, Total_Sales, Comments")

return $returnObject

Rozdělení

  • counts.totalFiltered: počet záznamů po filtrování
  • counts.totalSent: počet skutečně vrácených záznamů (po použití top)
  • entities: konečný soubor dat (nebo prázdný, pokud countOnly = true)

 

Všimněte si, že nástroj přesně řídí, které atributy jsou odesílány do modelu. Důležité je najít správnou rovnováhu.

Co je třeba zvážit

  • Kvalita konverzace: více dat → lepší poznatky
  • Výkon: více dat → delší zpracování
  • Kontextové okno: zejména lokální modely se mohou při přetížení zhoršit
  • Náklady: více tokenů → vyšší využití cloudových inferenčních serverů
  • Důvěrnost: při výběru polí vždy zvažte GDPR a citlivost dat

 

Závěr

Ať už nástroj vrátí jakýkoli objekt, sada 4D AI Kit jej transparentně serializuje a dodá modelu. Docela pohodlné, že?

 

Dotazování napříč tabulkami a počáteční systémová výzva

Dalším zajímavým zjištěním během tohoto projektu bylo, že model automaticky nerozumí vztahům mezi tabulkami. Například výzvy jako např:

Dejte mi 5 nejlepších zákazníků, jejich nejvyšší fakturu a jejich nejčastěji objednávaný produkt.

nevedly vždy ke spolehlivým výsledkům.

Problém byl jednoduchý: model si neuvědomoval, že ID v tabulce Klienti by mělo být použito k dotazu do tabulky Faktury nebo že řádky faktur se vztahují k výrobkům atd.

Jinými slovy, potřeboval jsem modelu poskytnout nějaké znalosti o struktuře, ale nezacházet příliš daleko. Moje požadavky byly následující:

  • Žádný pevně zakódovaný systémový dotaz: Nechci ručně aktualizovat výzvu při každé změně struktury.
  • Žádný úplný katalog struktury: Model nepotřebuje celé schéma, pouze relevantní vztahy.

 

Abych toho dosáhl, znovu jsem použil velmi šikovnou třídu od Thomase Maula: StructureInfo.4dm, která extrahuje pouze vztahy mezi tabulkami.

Z ní jsem vygeneroval svou úvodní systémovou výzvu:

var $relations : Collection:=This._relationsInfos()	
$systemPrompt:="You are a helpful assistant. I need your help to answer questions data stored in my application.\n"+\	
	"**CONTEXT**\n"+\
	"The application stores data about invoices, products and clients"+\
	"In some cases, you'll need to cross query several tables (dataClasses) in order to answer."+\
	"To help you, here are the application relations between tables (dataClasses):\n"+\
	JSON Stringify($relations)+"\n"+\
	"**INSTRUCTIONS**\n"+\
	"Analyze questions and answer step by step.\n"+\
	"Use the tools at your disposal to answer everytime you think they are relevant.\n"+\
	"**FORMATING**\n"+\
	"Use HTML everytime.\n"+\
	"Use bullet lists and Tables everytime everytime necessary\n"+\
	"**IMPORTANT**\n"+\
	"When calling tools, always include all required arguments in valid JSON.\n"+\
	"Do not call a tool with empty arguments. If a value is missing, choose a reasonable default.\n"+\
	"Always double check tools results before answering. Especially when they rely on vector search. \n"+\
	"Indeed they may return results not matching with your search intention.\n"+\
	"When tool calling returns data not related with the initial question, or that you cannot use to answer,\n"+\
	"avoid detailing such results too much and stay short.\n"

Kombinací těchto metadat o vztazích s informacemi o třídě dat vrácenými jednotlivými nástroji byl model konečně schopen pochopit, jak řetězit volání nástrojů napříč tabulkami.

Tím se výrazně zlepšila kvalita a přesnost odpovědí modelu, zejména u analýz s více tabulkami, jako např:

nejlepší zákazníci podle tržeb

nebo

nejčastěji objednávané produkty

nebo

největší faktury na zákazníka

Uživatelské prostředí: otevření formuláře 4D přímo z konverzačního uživatelského rozhraní

Při svých předchozích experimentech s RAG jsem často zobrazoval výsledky v samostatném poli se seznamem. Tento přístup fungoval, ale měl několik nevýhod:

  • Potřeboval jsem, aby model v samostatné skryté části poskytoval seznam ID subjektů, které se mají zobrazit v seznamu. To znamenalo více tokenů, pomalejší odezvy a další triky v HTML (například skrytí seznamu ID uvnitř komentovaného bloku).
  • Vyžadovalo to další práci na tom, aby byl listbox dostatečně obecný pro práci s různými typy entit (klienti, produkty, faktury, …).
  • Omezovalo to uživatelské rozhraní a působilo to méně integrovaně do aplikace.

 

Pro tento projekt jsem chtěl něco jednoduššího, elegantnějšího a pro uživatele přirozenějšího.

Proto jsem přijal novou strategii: pokaždé, když UI zmíní nějakou entitu, vygeneruje vlastní hypertextový odkaz, který přímo otevře odpovídající formulář 4D, filtrovaný na vybranou entitu.

Ukázalo se, že je to překvapivě snadné. Jednoduše jsem do systémové výzvy přidal následující pokyny:

"**CUSTOM URL HANDLING**\n"+\	
"Tools responses give information about the form to open when available, the dataClass and entities ID\n"+\
"When you display any element coming from a tool response, you must use a custom url so that the user can open the corresponding form\n"+\
"Such custom url must follow the following syntax examples:\n"+\
"<a href=\"myapp://openform?form=Products&dataClass=PRODUCTS&entities=989511\">A single product</a>\n"+\
"<a href=\"myapp://openform?form=Invoices&dataClass=INVOICESS&entities=654KJY,6467HGS,79864JSD\">A list of invoices</a>\n"

Protože mé nástroje vždy vracejí příslušný formulář, dataClass a seznam entit, má model vše, co potřebuje ke správnému vygenerování těchto odkazů. Modely umělé inteligence jsou v tomto druhu strukturovaného výstupu velmi dobré.

Zpracování vlastních adres URL v systému 4D

Jediné, co jsem na straně 4D potřeboval, byl malý mechanismus filtrování URL ve webové oblasti, který by zachytil odkazy myapp:// a otevřel správný formulář se správným výběrem entit:

Function webAreaEventHandler($formEventCode : Integer)
	var $formToOpen : Text
	var $entitySelectionToShow : 4D.EntitySelection
	var $queryObject : Object

	Case of 
		: ($formEventCode=On Load)
			ARRAY TEXT($filters; 0)
			ARRAY BOOLEAN($allowDeny; 0)
			APPEND TO ARRAY($filters; "myapp://*")  // Intercept all URLs starting with myapp://
			APPEND TO ARRAY($AllowDeny; False)  //Allow
			WA SET URL FILTERS(*; "Web Area"; $filters; $allowDeny)

		: ($formEventCode=On URL Filtering)
			$url:=WA Get last filtered URL(*; "Web Area")

			// Parse the URL to determine what to do
			Case of 
			: ($url="myapp://openform?@")
				$queryObject:=This.queryObjectFromUrl($url)
				If ($queryObject=Null)
					return 
				End if 

				If ($queryObject.entitiesCollection.length>0)
					$entitySelectionToShow:=ds[$queryObject.dataClass].query("ID in :1"; $queryObject.entitiesCollection)
					CALL WORKER("Generic"; "W_Generic"; $queryObject.form; True; $entitySelectionToShow)
				Else 
					CALL WORKER("Generic"; "W_Generic"; $queryObject.form; False)
				End if 
			End case 
	End case

Výsledek

Konečným výsledkem je velmi hladké uživatelské prostředí, kde konverzační uživatelské rozhraní hladce splývá se zbytkem aplikace 4D.

Uživatelé mohou chatovat s umělou inteligencí, zkoumat data a okamžitě otevírat nativní formuláře 4D, a to vše bez změny základní logiky nebo struktury aplikace.

Moderní model interakce, který se nachází přímo nad klasickou 4D aplikací… téměř bez zásahu.

blank

Další nástroj: tool_createInvoice

Ukázková databáze poskytnutá v projektu GitHub obsahovala jen několik faktur, což nebylo zdaleka dost na to, aby interakce s UI byla zajímavá. Potřeboval jsem více dat.

Vytváření vlastního formuláře nebo psaní další rutiny pro generování faktur mi připadalo pro účely této ukázky zdlouhavé a irelevantní. A pak mi to došlo: Všechno, co jsem potřeboval, jsem už měl.

  • Konverzační uživatelské rozhraní.
  • Agenta umělé inteligence, který zná můj datový model.
  • Znalost klientů, produktů, cen, vztahů…

Tak proč nenechat AI vytvářet faktury přímo z chatovacího rozhraní?

Stačilo přidat nový nástroj: tool_createInvoice.

Můj přístup byl jednoduchý:

  • Implementovat jednoduchou funkci pro vytváření faktur uvnitř nástroje AI_ChatWithTools.
  • Celý proces zabalte do transakce:
    • Při chybě: vrátit zpět a poslat jasnou chybovou zprávu zpět do modelu.
    • V případě úspěchu: odevzdejte fakturu a vraťte její podrobnosti.
  • Pečlivě zdokumentujte schéma nástroje, zejména jeho vstupní parametry.
  • Pak… nechte GitHub Copilot vygenerovat schéma JSON uvnitř souboru AITools.json.

 

Výsledek?

Nyní mohu požádat umělou inteligenci, aby zcela sama vygenerovala zcela novou fakturu. Najde příslušného klienta, vybere produkty, vypočítá celkové částky a zavolá nástroj, a to vše prostřednictvím stejného konverzačního uživatelského rozhraní, které jsem vytvořil dříve.

Ukázalo se, že je to překvapivě elegantní způsob, jak generovat realistická testovací data.

blank

Jeden zajímavý postřeh: některé modely (zejména OpenAI GPT-4.1) mají tendenci žádat o potvrzení nebo alespoň o dostatečné vstupní údaje, než skutečně vytvoří fakturu… pokud jim výslovně nedáte pokyn, aby to nedělaly.

blank

Vykreslování HTML zpráv OpenAI

Jak již bylo zmíněno, tato část byla kompletně nakódována vibracemi. Použijte ji znovu, přizpůsobte si ji nebo ji ignorujte, podle toho, co vyhovuje vašim potřebám. Myšlenka je jednoduchá: vzít kolekci zpráv OpenAI a pěkně je vykreslit do HTML.

Ale naši koncoví uživatelé si samozřejmě vždy zaslouží víc než jen základní výpis textu. Proto jsem přidal několik funkcí zvyšujících kvalitu života:

  • Přehledné, strukturované rozvržení volání nástrojů, včetně vizuální indikace, když je nástroj spuštěn.

 

  • Tlačítko „Kopírovat“ na jedno kliknutí, které umožňuje snadno zkopírovat jakoukoli zprávu asistenta a vložit ji do dokumentu, ať už jde o Microsoft Word, Dokumenty Google nebo e-mail.

Díky tomu působí celá konverzace uhlazeně a profesionálně, a přitom je její implementace rychlá a nenáročná.

blank

  • Tlačítko kopírování pro každou tabulku, které uživateli umožňuje okamžitě vyjmout surová tabulková data a vložit je přímo do tabulky podobné aplikaci Excel.

To je mimořádně výhodné, když uživatelé chtějí manipulovat s daty nebo je porovnávat mimo aplikaci, aniž by museli cokoli exportovat.

blank

Možnosti tvorby grafů přímo v konverzačním uživatelském rozhraní

Při konverzaci s umělou inteligencí o fakturách, klientech nebo produktech uživatelé přirozeně očekávají grafy. Žebříčky, srovnání, trendy… vizuální náhledy jsou nyní součástí každého moderního prostředí.

Proto jsem se rozhodl vnést vykreslování inline grafů do konverzačního uživatelského rozhraní a ukázalo se, že je to překvapivě snadné, díky troše vibračního kódování pomocí GitHub Copilot.

Implementoval jsem to ve třech krocích:

1) Importovat Chart.js do souboru chat-template.html a rozšířit vykreslovací engine HTML tak, aby rozpoznával bloky <chart>…</chart>.

Zatímco umělá inteligence streamuje svou odpověď, malá animace CSS zobrazuje zástupný symbol grafu, čímž dodává UX vybroušený dojem.

2) Rozšiřte systémovou výzvu tak, aby výslovně učila UI, jak si vyžádat grafy. Přidala jsem instrukce, jako např:

"**CHARTS**\n"+\	
"Create charts for rankings, comparisons, trends, or distributions. Format: <chart>{...JSON...}</chart>\n"+\
"Available types: bar, line, pie, doughnut, radar, polarArea. Always include:\n"+\
"- \"type\": chart type\n"+\
"- \"data.labels\": array of x-axis labels\n"+\
"- \"data.datasets\": array with \"label\", \"data\" (numeric array), \"backgroundColor\" (color array)\n"+\
"- \"options.responsive\": true\n"+\
"- \"options.plugins.title\": {\"display\": true, \"text\": \"Chart Title\"}\n"+\
"- \"options.scales.y.beginAtZero\": true (for bar/line charts)\n"+\
"Use distinct vibrant colors (e.g., #4caf50, #2196f3, #ff9800, #e91e63, #9c27b0). Set \"legend.display\" to false for single datasets, true for multiple.\n"

3) Nechte UI generovat definice grafů v JSON, které webová oblast okamžitě vykreslí pomocí Chart.js.

blank

Výsledek je skutečně působivý: model vytváří smysluplné vizualizace přímo uvnitř toku konverzace, což výrazně obohacuje zážitek.

Přesto bych se při složitých výpočtech na model zcela nespoléhal. Pro produkční použití by bylo rozumné přidat řadu nástrojů, které se tomu věnují:

  • součty a kumulace
  • seskupování a agregace
  • časové souhrny
  • porovnávání období
  • extrakci klíčových ukazatelů výkonnosti

 

Společnost 4D by prováděla náročné a přesné výpočty a umělá inteligence by si je jednoduše vyžádala a vykreslila grafy na základě přesných a ověřených číselných údajů.

Dokonalá kombinace spolehlivosti 4D a uživatelského rozhraní poháněného umělou inteligencí.

Závěr

Takže… co teď?

V podstatě jsme vzali poněkud staromódní podnikovou aplikaci a naplnili ji moderním, konverzačním prostředím poháněným AI.

Ale vidět to jednoduše jako „další způsob, jak získat data“, by bylo zcela mimo podstatu věci.

Jistě, nepotřebujete konverzační uživatelské rozhraní, abyste získali „5 nejlepších zákazníků podle celkových tržeb v roce 2025“.

To zvládne základní obrazovka s několika filtry.

Ale velmi rychle si uvědomíte, že jde o něco jiného.

Je to nový způsob zkoumání vašich dat.

Pomocí jediného formuláře, chatovacího rozhraní, se uživatelé mohou ptát na cokoli: faktury, produkty, klienty… ať už chtějí tabulku, graf, nebo obojí.

Tím odpadá nutnost vytvářet nespočet specializovaných obrazovek pro trochu jiné potřeby vykazování.

A jakmile to uvidíte, pochopíte také, že to jde daleko za dotazování a zobrazování dat.

Skutečná hodnota nespočívá v odpovědi „ukaž mi tohle„.

Skutečná hodnota spočívá v odpovědi „pomozte mi to pochopit„.

Vaše výzva by již neměla znít:

Nakreslete graf porovnávající roky 2024 a 2025.

ale místo toho:

Uveďte podrobnou zprávu o prodeji za rok 2025, včetně celkového prodeje, 5 nejlepších produktů podle tržeb, 5 nejlepších klientů podle prodeje, trend prodeje v průběhu roku a nezaplacené faktury. Zobrazte příslušné grafy a tabulky a vysvětlete všechny pozoruhodné trendy, příležitosti a rizika. Porovnejte také výkonnost produktů s rokem 2024 a navrhněte akční poznatky pro zlepšení prodeje a cashflow. Zahrňte přehled výkonnosti podle jednotlivých klientů a produktů s klíčovými ukazateli. Chci jak čísla, tak vysvětlení a akční postřehy. Vaše zpráva bude obsahovat srovnání mezi roky 2024 a 2025. Cíle takové zprávy jsou: jak zvýšit prodej, na které klienty se zaměřit, jak zvýšit výkonnost produktu.

A právě takovou odpověď dostanete vy – a vaši uživatelé:

blank

Jednotné konverzační rozhraní, hladce integrované do vaší 4D aplikace, schopné vhledu, uvažování, vizualizace, tvorby…

Tohle není funkce.

Je to krok k nové generaci podnikových aplikací.

Jak to znovu využít ve vlastním projektu?

Pokud ve vás čtení tohoto příspěvku a hraní si s aplikací vzbudilo zájem, můžete jednoduše:

  • Zkopírujte následující soubory do svého projektu:
    • Třídy:
      • AI_ChatWithTools.4dm
      • ChatHTMLRenderer.4dm
      • formAIChat.4dm
      • StructureInfo.4dm
    • Formulář
      • AIChat
    • Zdroje
      • AIprovider.json
      • AITools.json
      • chat-template.html
      • chat-template.css
      • tool-icon.svg
    • Proveďte potřebné úpravy
      • Implementace systémové výzvy a nástrojů v souboru AI_ChatWithTools.4dm
      • Následná definice nástrojů v souboru AITools.json (stačí použít AI!).
      • Přizpůsobte otevírání formuláře vaší aplikaci v souboru formAIChat.webAreaEventHandler()
      • Nastavení poskytovatele AI v souboru AIprovider.json

 

A to je vše!

Na závěr uvedu několik doplňujících poznámek:

V tomto příkladu je veškerá logika nástrojů implementována ve třídě AI_ChatWithTools. Udělal jsem to proto, že mým cílem bylo být co nejméně rušivý, a protože projekt neimplementuje třídy DataClasses. V závislosti na architektuře vaší kódové základny by lepší praxí mohlo být, aby takové nástroje cílily na funkce DataClasses.

Celý tento projekt funguje perfektně s OpenAI a modelem gpt-4.1 nebo vyšším. Práce s lokálním modelem vyvolává další problémy, které lze diskutovat na fóru 4D!

 

Mathieu Ferry
• Vedoucí produktového týmu 4D •Mathieu se připojil ke 4D v roce 2020 jako vedoucí produktového týmu. Jeho tým se skládá z Product Ownerů, zástupců uživatelů ve 4D. Spolupracují ruku v ruce s týmem inženýrů a jejich role zahrnuje stanovení priorit, rozsahu a ověřování, zda nové funkce budou odpovídat očekáváním uživatelů 4D. Mathieu dříve působil jako projektový ředitel a týmový manažer v různých předních odvětvích IT divizí – automobilového průmyslu, bezpečnosti, reklamy, specializující se na mezinárodní kontexty a cloudově orientované služby.