Using Claude or CoPilot to generate templates

Hello everyone,

I have spent the last few days trying to get Claude and CoPilot to generate templates to help integrate the Florence Medical API into my C11.1.13855 desktop app. Both have generated some seemingly comprehensive clw, inc, tpl and tpw files. However, upon registering these templates, they always give errors. My guess is that the respective LLM’s don’t generate the correct template language.

I know John Hickey has done a lot of work with Claude and generating code. I was hoping he and others could give me some insight, tips, etc. Maybe I’m not using the correct prompts for the AI engines. Ay thoughts, tips or similar experiences?

Thank you,

Jeff King

Well, you could post your templates and/or what the errors are and then correct them manually if you think the overall function is correct.

Hi Kevin,

I have attached an image of the errors when registering the templates. Also, I have attached the tpl and tpw files CoPilot generated. Looking forward to learning.

Jeff


FlorenceAPI.tpl (4.6 KB)
FlorenceAPI.tpw (2.7 KB)

Hi Jeff.

Out the box I’d expect the LLM’s to be pretty horrific at generating templates. I haven’t really bothered to try specifically because I don’t have much expectation.

There are a few things that spring to mind;

a) Templates are just ways of pre-writing Clarion code, and injecting it into embed points. Without giving the LLM an example of the code ou want injected, and where, I’m not sure that anything useful can be expected.

b) TPL and TPW files are different to regular code because they contain a mix of template language instructions, and code-to-generate (ie Clarion instructions) all mixed together. Unless an LLM was specifically trained on this it’s unlikely to generate anything useful.

c) LLM’s are usually trained on millions of documents. I’m guessing their corpus of Clarion Template files is as close to zero as being a rounding error.

Update: having looked at the TPL and TPW you supplied, I can confirm that they are garbage, and not really helpful to your cause.

3 Likes

If you give the AI the template language reference PDF and one or two solid examples of what a proper Clarion template looks like, it can do surprisingly well.

Like anything else with AI, it lives or dies on context: show it the patterns you want, tell it what embed points and structures are valid, and be explicit that it must not invent syntax, keywords, or template directives.

Where people get burned is asking it to “write a template” with no references and no known-good sample. Then it fills in the gaps with confident nonsense.

But if you anchor it with the reference doc plus a real template (even a small one) and a clear goal, you can often get something that’s at least a strong first draft, and sometimes close to production-ready after a quick pass by someone who knows templates.

Hi

One thing I found useful when using GH Copilot Cli was to decompile the clarion help file to html.

hh.exe -decompile "C:\output-folder" "C:\path\to\file.chm"

Then you can teach it how to use the help files and create a skill to search it.

It’s been really useful in my VS Code language extension development.

Mark

2 Likes

Thanks Charles! I might try this but I wonder if it is “legal” to send the PDF written by SoftVelocity. Thoughts?

Thanks Mark! As I mentioned to Charles post, is this “legal”, sending a help document created by SoftVelocity?

Thanks Bruce!

I spent a few hours trying this with no success, as you saw by the samples I included here. Neither could generate a small template that I could successfully register. Both said the tpl/tpw file had to be saved as ANSI, something to do with BOM, etc. Copy and paste to NotePad/NotePad++ and saving/converting from UTF8 to ANSI did not help. I might try the suggestions from Charles and Mark.

Jeff

If you mean uploading or sharing the SoftVelocity help/PDF publicly or with other people, then no — that wouldn’t be OK. It’s copyrighted documentation.

If you mean using it privately as reference (including giving it to an AI locally or in your own account to help answer questions), that’s generally fine and no different to searching the help yourself.

The line is redistribution: don’t publish or share the documentation itself or large verbatim excerpts. Private use as reference is OK.

It’s also worth noting that third-party sites like https://clarion.help
have existed for years. Presumably permission was granted or at least it hasn’t been challenged, which suggests SoftVelocity aren’t particularly opposed to the information being publicly accessible — but that still doesn’t change the redistribution line above. If you mean uploading or sharing the SoftVelocity help/PDF publicly or with other people, then no — that wouldn’t be OK. It’s copyrighted documentation.

I’m no lawyer though.

Mark

1 Like

I’ve done that and it works well.

You can also just right-click on the .chm file with 7-Zip and select Extract and it will dump it for you.

Charles

1 Like

The technical term is slop.

AI slop, yep. :slightly_smiling_face:

But to be fair to the AI, this is the same paradigm we have dealt with forever:

Garbage in, garbage out.

If you give it a vague request and no authoritative reference or known-good example, it will happily “complete the pattern” and you end up with confident-looking nonsense. Templates are especially unforgiving, because they are basically their own little language with strict rules, directive syntax, and expected structure.

If you want something other than slop, you have to feed it real signal: the template language reference, a couple of correct templates to imitate, and explicit instructions like “do not invent directives or syntax, and if you are unsure, ask or say you are unsure.”

Do that, and the output usually goes from unusable to a decent first draft that a template-savvy dev can tighten up quickly.

This will probably get you going, and just a few reasons why an Ai will struggle to write template code…

Summary

Undocumented Features…


#TEMPLATE(FlorenceAPI,'Florence API Integration'),Family('ABC','Clarion','CW20')
#!
#! Undocumented Rule - You can't have blank lines here. So fill them with a template comment at the very least.
#!
#EXTENSION(FlorenceAPI_GlobalExtension,'Florence API Global Extension'),APPLICATION
#!
#Sheet,HScroll  #! Organising stuff in #Tab's is a nice way of organising complex templates
    #Tab('0&1 Start') #! Using 0&1 means you press 1, 2 3 to jump quickly to the #Tab you want.
        #Display() #! Blank line from the top of the #Tab
        #PROMPT('Environment',Drop('Dev|UAT|Prod')),%EnvChoice,DEFAULT('Dev')
        #display()
    #Enable(%EnvChoice = 'Dev') #! Example of enabling other prompts on this tab or other tabs based on the value in %EnvChoice
        #PROMPT('Base URL (Dev)',@s255),%DevBaseURL   #! @s255 is a pseudo undocumented feature the AI probably wont pick up on
    #EndEnable
    #Enable(%EnvChoice = 'UAT')
        #!PROMPT('Base URL (UAT)',@s512),%UATBaseURL   #! Undocumented Rule - You can put comments in between prompts @s512 is just too big
        #Display('Base URL (UAT)') #! This is here because you can control the Prompt position better especially when using ,AT in the #Prompt
        #PROMPT('Base URL (UAT)',Text),%UATBaseURL   #! If you need bigger swap to TEXT eg
    #EndEnable
    #Enable(%EnvChoice = 'Prod')
        #Display('Base URL (Prod)') #! This is here because you can control the Prompt position better especially when using ,AT in the #Prompt
        #PROMPT('Base URL (Prod)',TEXT),%ProdBaseURL,AT(,,180,15)  #! Adjust for C7+ Wide Template windows
    #EndEnable
    #EndTab
    #Tab('0&2 Authentication')
        #Display('')
        #Display('Token URL')
        #PROMPT('Token URL',Text),%TokenURL
        #Display('')
        #Display('Revoke URL')
        #PROMPT('Revoke URL',Text),%RevokeURL
        #Display('')
        #Display('Client ID')
        #PROMPT('Client ID',Text),%ClientID,AT(,,180,20) #! Adjust for C7+ Wide Template windows
        #Display('')
        #Display('Client Secret')
        #PROMPT('Client Secret',Text),%ClientSecret
    #EndTab
    #Tab('0&3 Binder Endpoints')
        #Display('')
        #Display('List Binders URL')
        #PROMPT('List Binders URL',Text),%BindersListURL
        #Display('')
        #Display('Create Binder URL')
        #PROMPT('Create Binder URL',Text),%BindersCreateURL
        #Display('')
        #Display('Delete Binder URL')
        #PROMPT('Delete Binder URL',Text),%BindersDeleteURL
        #Display('')
        #Display('Upload Document URL')
        #PROMPT('Upload Document URL',Text),%BindersUploadDocURL
        #Display('')
        #Display('Download Document URL')
        #PROMPT('Download Document URL',Text),%BindersDownloadDocURL
    #EndTab
    #Tab('0&4 Consent Export')
        #Display('')
        #Display('Consent Export URL')
        #PROMPT('Consent Export URL',Text),%ConsentExportURL
        #Display('')
        #Display('Default Save Folder')
        #PROMPT('Default Save Folder',Text),%ConsentSaveFolder
        #Display('')
        #PROMPT('Export Format',Drop('JSON|Raw|Auto')),%ConsentExportFormat,DEFAULT('Auto')
    #EndTab
    #Tab('0&5 Document Export (eBinders)')
        #Display('')
        #Display('Document Export URL')
        #PROMPT('Document Export URL',Text),%DocExportURL
        #Display('')
        #Display('Document Metadata URL')
        #PROMPT('Document Metadata URL',Text),%DocMetadataURL
        #Display('')
        #Display('Document Version URL')
        #PROMPT('Document Version URL',Text),%DocVersionURL
        #Display('')
        #PROMPT('Include Binary',Check),%DocIncludeBinary,Default(%True),At(10)  #! At(10) positions the check box on the left with a massive space for the prompt text
        #Display('')
        #PROMPT('Metadata Only',Check),%DocMetadataOnly,Default(%True),At(10) #! At(10) positions the check box on the left with a massive space for the prompt text
        #Display('')
        #PROMPT('Default Export Format',Drop('JSON|PDF|Raw|Auto')),%DocExportFormat,DEFAULT('Auto')
        #Display('')
        #Display('Default Save Folder')
        #PROMPT('Default Save Folder',Text),%DocSaveFolder
    #EndTab
    #Tab('0&6 Runtime Options')
        #Display()
        #PROMPT('Enable Logging',Check),%EnableLogging,Default(%False),At(10) #! At(10) positions the check box on the left with a massive space for the prompt text
        #Display()
        #Display('Log File Path')
        #PROMPT('Log File Path',Text),%LogFilePath
        #PROMPT('Timeout (0-100 seconds)',Spin(@n3,0,100)),%Timeout #! Use Spin for a range if you dont use #Validate after a #Prompt.
#!      #Validate(%GrpCallAValidateGroup,'Put Your Message Here if you dont want to put a %String')
#!      #Validate(%GrpCallAValidateGroup,'Put Your Message Here if you dont want to put a %String')
        #! Undocumented Rule - You can stack as manany #Validates after a prompt for sequential processing.
        #PROMPT('Enable Debug Mode',Check),%DebugMode,At(10) #! At(10) positions the check box on the left with a massive space for the prompt text
    #EndTab
    #Tab('0&7 Helpers')
        #Display()
        #PROMPT('Generate Test Connection procedure',Check),%GenTestConn,At(10)
        #PROMPT('Generate Show Last Response procedure',Check),%GenShowLastResp,At(10)
        #PROMPT('Generate Binder Manager menu item',Check),%GenBinderMenu,At(10)
        #PROMPT('Generate Consent Export menu item',Check),%GenConsentMenu,At(10)
        #PROMPT('Generate Document Export menu item',Check),%GenDocExportMenu,At(10)
    #EndTab
#EndSheet

#AT(%GlobalMap)
    INCLUDE('FlorenceAPI.inc'),ONCE
#ENDAT

#AT(%GlobalData)
FlorenceAPIInst   FlorenceAPIClass
FlorenceAPI       &FlorenceAPIClass
#ENDAT

#AT(%ProgramSetup)
    ! CODE ?? Probably not
    FlorenceAPI &= FlorenceAPIInst

    CASE %EnvChoice
    OF 1
      FlorenceAPI.SetBaseURL(%DevBaseURL)
    OF 2
      FlorenceAPI.SetBaseURL(%UATBaseURL)
    OF 3
      FlorenceAPI.SetBaseURL(%ProdBaseURL)
    END

    FlorenceAPI.SetTokenURL(%TokenURL)
    FlorenceAPI.SetRevokeURL(%RevokeURL)
    FlorenceAPI.SetClientID(%ClientID)
    FlorenceAPI.SetClientSecret(%ClientSecret)

    FlorenceAPI.SetBindersListURL(%BindersListURL)
    FlorenceAPI.SetBindersCreateURL(%BindersCreateURL)
    FlorenceAPI.SetBindersDeleteURL(%BindersDeleteURL)
    FlorenceAPI.SetBindersUploadDocURL(%BindersUploadDocURL)
    FlorenceAPI.SetBindersDownloadDocURL(%BindersDownloadDocURL)

    FlorenceAPI.SetConsentExportURL(%ConsentExportURL)
    FlorenceAPI.SetConsentExportFormat(%ConsentExportFormat)
    FlorenceAPI.SetConsentSaveFolder(%ConsentSaveFolder)

    FlorenceAPI.SetDocumentExportURL(%DocExportURL)
    FlorenceAPI.SetDocumentMetadataURL(%DocMetadataURL)
    FlorenceAPI.SetDocumentVersionURL(%DocVersionURL)
    FlorenceAPI.SetDocumentExportFormat(%DocExportFormat)
    FlorenceAPI.SetDocumentIncludeBinary(%DocIncludeBinary)
    FlorenceAPI.SetDocumentMetadataOnly(%DocMetadataOnly)
    FlorenceAPI.SetDocumentSaveFolder(%DocSaveFolder)

    FlorenceAPI.SetLogging(%EnableLogging,%LogFilePath)
    FlorenceAPI.SetTimeout(%Timeout)
    FlorenceAPI.SetDebug(%DebugMode)

#ENDAT

Thanks for the corrected template Rich. I was able to get it to register in C11.1. However, when I compile a test app with the global template attached, I get a series of errors as seen in the attached image. Can you help?

In addition, I have AI generated clw and inc files. Would you like to take a look at these as well?

Jeff