{ Analytica Model OpenAI_API_lib, encoding="UTF-8" }
SoftwareVersion 6.3.6
{!-60000|Attribute AcpStyles}
LinkLibrary OpenAI_API_lib
Title: OpenAI API lib (ver. 0.4)
Description: A set of function to assist in using the OpenAI API for Large Language Models (LLMs).~
~
These are useful:~
(a) To get a similarity embedding for snippet(s) of text.~
(b) To get a one-off completion to a prompt.~
(c) To manage a chat conversation.~
~
To use these libraries, you must get an OpenAI API key directly from OpenAI.~
~
This library requires the Analytica Enterprise edition or better.
Author: Lonnie Chrisman, Ph.D.~
Lumina Decision Systems
Date: Thu, Jul 20, 2023 12:00 PM
NodeSize: 64,24
NodeInfo: 1,,,,,,,0,,,,,,0
DiagState: 2,85,7,1713,680,17,10
WindState: 2,741,222,739,453
FontStyle: Arial,15
FileInfo: 0,LinkLibrary OpenAI_API_lib,2,2,0,0,..\Src\AI Assistant Prototype\OpenAI API lib.ana
Button Save_API_key_with_yo
Title: Save API key with your model.
NodeLocation: 224,226,1
NodeSize: 128,20
OnClick: if API_Key_for_OpenAI='' or API_Key_for_OpenAI=Null then Error("API key not entered");~
~
If IsNull(isin of OpenAI_API_lib) then Error("Can't save with your model because no model is loaded -- this library has been opened directly.");~
~
LocalAlias parentMod := isin of OpenAI_API_lib;~
Local existing := HandleFromIdentifier("OPENAI_API_KEY");~
LocalAlias v := if IsNull(existing) Then CreateNewObject(Constant, parentMod, "OpenAI API key", "OpenAI_API_Key") Else existing;~
v := API_Key_for_OpenAI;~
ShowWindow(v, 'OnDiagram')~
Button Save_API_key_in_env_
Title: Save API key in env var
NodeLocation: 224,140,1
NodeSize: 128,20
OnClick: if API_Key_for_OpenAI='' or API_Key_for_OpenAI=Null then Error("API key not entered");~
Local existingKey := GetProcessInfo("env:OPENAI_API_KEY");~
Local ok := true;~
~
if existingKey<>'' and existingKey<>Null and MsgBox("Your OPENAI_API_KEY environment variable is already set. Do you want to changed it?", 4, "Warning: Change it?")= /*No*/7 Then ~
ok := false;~
~
if ok then~
Set_Env_Var("OPENAI_API_KEY", API_Key_for_OpenAI)
Button Change_your_API_key
Title: Change your API key
NodeLocation: 224,298,1
NodeSize: 128,20
OnClick: InvalidateResult(API_Key_for_OpenAI);~
Local q := "(Please get an API key (Secret key) from OpenAI)"; ~
value of API_Key_for_OpenAI := AskMsgText(q,"Enter OpenAI API key");~
API_Key_for_OpenAI
Text Te1460981395
Title: An OpenAI API Key is required...
Description: ~
...to use this library. You need to get your own API key from OpenAI. Once you have a key, you can:~
• Require the user to enter it each time she uses your model.~
• Save it in an environment variable named OPENAI_API_KEY. You won't have to re-enter again an this computer.~
~
~
~
• Save it with your model. Your model users will never have to enter it, but their usage will get billed to your OpenAI account. ~
If you plan to post your model to ACP on Lumina's server, you'll need to use this option.~
~
~
~
If you have previously entered a key and you need to change it, use this button:
NodeLocation: 472,184,-1
NodeSize: 440,160
NodeInfo: 1,,,,1,1
NodeColor: 58981,65535,52427
Module Open_AI_lib_internal
Title: Open AI lib internals
Author: Lonnie Chrisman~
Lumina Decision Systems
Date: Thu, Jul 20, 2023 2:09 PM
NodeLocation: 1032,56,1
NodeSize: 64,24
DiagState: 2,99,45,1541,677,17,10
Constant Sys_Root_System32
Title: Sys_Root_System32
Definition: FileFullPath( "System32", GetProcessInfo("env:SystemRoot"))
NodeLocation: 304,56,1
NodeSize: 88,24
Function Set_Env_Var( name, value : atom text)
Title: Set Env Var
Description: Sets a persistent user environment variable to the given value.~
~
To remove the env var, use the empty text ("") for the value.
Definition: if SelectText(AnalyticaEdition,1,3)="ACP" Then Error("Sorry, you cannot set an environment variable from a model running on ACP");~
~
Local program := FileFullPath( "setx.exe", Sys_Root_System32 );~
RunConsoleProcess( program, f"setx ""{name}"" ""{value}""" )
NodeLocation: 488,56,1
NodeSize: 64,24
WindState: 2,539,329,720,350
Variable API_Key_for_OpenAI
Title: API Key for OpenAI
Description: To use this library, you must get an API key from OpenAI. This will require you to create an account with them and supply some credit card info. Using the APIs is not free, but it is extremely cheap for small-scale usage. ~
~
Once you have an API key, you can provide to this library in one of two ways:~
(a) Set an environment variable named OPENAI_API_KEY.~
(b) Add a variable named OPENAI_API_KEY to your model and set it to a text value.~
~
If you have done neither, the library will ask you for your key and will let you chose which method to use. (But it won't set it from within ACP).~
~
Adding it to your model will allow users of your model to run with your key. This means their usage will show up on your OpenAI bill, but they won't have to get their own API key.
Definition: if HandleFromIdentifier("OPENAI_API_KEY")<>Null Then~
Evaluate("OPENAI_API_KEY")~
else (~
Local envkey := GetProcessInfo("env:OPENAI_API_KEY");~
if envkey<>null then envkey else (~
/* Key is not set. Ask user to configure it. */~
Local q := "(Please get an API key (Secret key) from OpenAI)"; ~
AskMsgText(q,"Enter OpenAI API key");~
) ~
)
NodeLocation: 120,56,1
NodeSize: 64,24
WindState: 2,98,82,1263,518
ValueState: 2,273,434,1028,353,,MIDM
Index Ada_embedding
Title: Ada embedding
Description: This indexes the text embedding returned from the text-embedding-ada model.
Definition: 1..1536
NodeLocation: 120,184,1
NodeSize: 64,24
Constant Text_embedding_model
Title: Text embedding model name
Definition: 'text-embedding-ada-002'
NodeLocation: 120,120,1
NodeSize: 72,24
Index Rec_Embedding_for
Title: Rec_Embedding_for
Definition: ['model','input']
IndexVals: ['item 1']
NodeLocation: 120,256,1
NodeSize: 88,24
Variable OpenAI_headers
Att_PrevIndexValue: ['Authorization','Content-type']
Title: OpenAI headers
Definition: Table(Self)('Bearer ' & API_Key_for_OpenAI,'application/json')
IndexVals: ['Authorization','Content-type']
NodeLocation: 312,120,1
NodeSize: 64,24
ValueState: 2,356,362,953,270,,MIDM
ReformDef: [Undefined,Self]
Variable OpenAI_header_text
Title: OpenAI header text
Definition: JoinText(f"{IndexValue(OpenAI_headers)}:{OpenAI_headers}",OpenAI_headers,Chr(13))
NodeLocation: 312,192,1
NodeSize: 64,24
ValueState: 2,372,378,761,220,,MIDM
Constant OpenAI_Embedding_URL
Title: OpenAI Embedding URL
Definition: 'https://api.openai.com/v1/embeddings'
NodeLocation: 480,120,1
NodeSize: 72,24
Function Embedding_resp_json( txt )
Title: Embedding response json
Description: Returns the JSON response from a call to get the similarity embedding for text.
Definition: Local inds := IndexesOf(txt);~
Local flat := Flatten(if txt=null then 'Null' else txt,...inds);~
Local req := MakeJson(Array( Rec_Embedding_for, ~
[Text_embedding_model,\flat]));~
Local resp := ReadFromURL( OpenAI_Embedding_URL, method:'POST', httpHeaders: OpenAI_header_text, httpContent: req );~
ParseJSON(resp)
NodeLocation: 328,264,1
NodeSize: 80,24
WindState: 2,355,78,1220,436
Variable OAL_Avail_model_resp
Title: Available models response
Definition: ReadFromURL( OpenAI_Models_URL, 'GET', httpHeaders:OpenAI_header_text )
NodeLocation: 664,192,1
NodeSize: 72,24
ValueState: 2,380,82,601,569,,MIDM
Constant OpenAI_Models_URL
Title: OpenAI Models URL
Definition: 'https://api.openai.com/v1/models'
NodeLocation: 664,120,1
NodeSize: 64,24
Index OpenAI_Model_Name
Title: OpenAI Model Name
Definition: ComputedBy(OAL_Avail_Models)
NodeLocation: 848,120,1
NodeSize: 64,24
ValueState: 2,52,58,620,704,,MIDM
Aliases: Alias Al125226643
Variable OAL_Avail_Models
Title: Available Models
Definition: Local r := #ParseJSON(OAL_Avail_model_resp)[.Member='data'];~
LocalIndex I := 1..size(r,listLen:true);~
Local data := #Slice(r,I);~
LocalIndex models := Slice(data[.member='id'],CopyIndex(I));~
OpenAI_Model_Name := SortIndex(models);~
Local res := data[I=@Models][Models=OpenAI_Model_Name];~
if res.Member='permission' then Slice(#res,1) else res~
NodeLocation: 848,192,1
NodeSize: 64,24
ValueState: 2,128,13,1353,687,,MIDM
Aliases: FormNode Fo89320851
ReformVal: [Sys_LocalIndex('Member'),OpenAI_Model_Name]
Att_ResultSliceState: [Self,1,OpenAI_Model_Name,1,Sys_LocalIndex('Member'),1]
{!40300|Att_SlicerPopupSize: 227,32}
Index OpenAI_Function_Item
Title: OpenAI Function Item
Definition: ['name','description','parameters']
NodeLocation: 1008,120,1
NodeSize: 64,24
ValueState: 2,22,594,416,303,,MIDM
Constant OpenAI_Chat_URL
Title: OpenAI Chat URL
Definition: 'https://api.openai.com/v1/chat/completions'
NodeLocation: 664,56,1
NodeSize: 64,24
Index Chat_API_field
Att_PrevIndexValue: ['model','messages','functions','function_call','temperature','top_p','n','stop','max_tokens','presence_penalty','frequency_penalty','user']
Title: Chat API field
Definition: ['model','messages','functions','function_call','temperature','top_p','n','stop','max_tokens','presence_penalty','frequency_penalty','user']
NodeLocation: 120,480,1
NodeSize: 64,24
WindState: 2,2060,192,720,350
Function Chat_Message_history( messages : text orNull all [Chat_index] ;~
role : text [Chat_index] ;~
Chat_index : Index ;~
~
functionName : optional [ Chat_index ] = null ;~
functionCall : optional reference orNull [Chat_index] = null~
)
Title: Chat_Message_history
Definition: Table(Chat_message_field)(role,messages,functionName,functionCall)
NodeLocation: 496,408,1
NodeSize: 96,24
WindState: 2,231,34,994,713
DefnState: 2,203,868,416,303,0,DFNM
ReformDef: [Undefined,Chat_message_field]
Index Chat_message_field
Att_PrevIndexValue: ['role','content','name','function_call']
Title: Chat message field
Definition: ['role','content','name','function_call']
NodeLocation: 288,480,1
NodeSize: 64,24
Function Chat_record( conversation ;~
modelName : text atom ;~
functions : optional ... Object;~
~
temperature : optional nonNegative atom;~
top_p : optional positive atom;~
~
Completion_index : optional Index ;~
stop_sequences : optional text ;~
~
max_tokens : optional atom;~
presence_penalty, frequency_penalty : optional number atom~
)
Title: Chat record
Description: Assembles the record that will be sent to the OpenAI API message for a chat completion.~
The result is a record on the Chat_API_field index.~
This is a helper for the implementation of Chat_completion(...).~
~
«conversation» is the conversation history, usually obtained by calling Chat_Message_History(...).~
~
For the remaining parameters, see Chat_completion's description.
Definition: Table(Chat_API_field)(modelName,\conversation,API_Functions_Rec(...functions),Null,UndefToNull(temperature),UndefToNull(top_p),if IsNotSpecified(Completion_index) then Null else IndexLength(Completion_index),Null,UndefToNull(max_tokens),UndefToNull(presence_penalty),UndefToNull(frequency_penalty),GetProcessInfo('UserName'))
NodeLocation: 672,408,1
NodeSize: 64,24
WindState: 2,1354,157,955,667
DefnState: 2,359,614,1087,557,0,DFNM
ReformDef: [Undefined,Chat_API_field]
Function Chat_completion_raw_( messages : text all [Chat_index] ;~
role : text [Chat_index] ;~
Chat_index : Index ;~
~
modelName : text atom = 'gpt-3.5-turbo' ;~
~
functions : optional ... Object;~
~
temperature : optional nonNegative atom ;~
top_p : optional positive atom ;~
~
Completion_index : optional Index ;~
stop_sequences : optional text ;~
~
max_tokens : optional atom ;~
presence_penalty, frequency_penalty : optional number atom~
)
Title: Chat completion raw response
Description: This returns the next response from in a Chat (ala ChatGPT) given the history of messages so far.~
~
Required parameters:~
«messages» : The sequence of messages so far, in order, indexed by «Chat_index».~
«role» : Each message has a role, which must be one of 'system', 'user', 'assistant', or 'function'.~
«Chat_index»: Indexes the sequence of messages in the conversation~
~
Return value:~
The raw parsed json response from the API call.~
~
Optional parameters:~
«modelName»: The OpenAI model to use. It must support Chat. 'gpt-3.5', 'gpt-3.5-turbo' and 'gpt-4' are common choices.~
«functions» : One or more functions that the LLM can call during its completions.~
«temperature»: A value between 0 and 2. ~
Smaller values are more focused and deterministic, Higher values are more random. Default=1.~
«top_p»: A value 0function feature), this assembles and returns a record with the function description in the form desired by the API. The data is an Analytica record which can be directly converted to JSON using MakeJSON.~
Definition: Local proto := FindInText("^\s*\(\s*(?.*)\s*\)|(?.*)\s*$", parameters of (fn), subpattern:'a', return:'S');~
proto := TextReplace(proto,"\[\s*([\w_]+)\s*(,\s*[\w_]+\s*)*\]","",all:true,re:true); { Remove [I,J] decls to get rid of commas }~
proto := TextReplace(proto,":([^,;]+),",":\1;",all:true,re:true); { Make quantifier group separators consistent, always ; }~
~
LocalIndex paramName := TextTrim(SplitText(paramNames of (fn),','));~
Local qualifiers := FindInText(f"\b{paramName}\b[^;:]*:\s*([^;]+)", proto, caseInsensitive:true, re:true, subpattern:1, return:'S');~
Local bRequired := FindInText("opt|=", qualifiers,re:true)=0 or qualifiers=null;~
Local dtype := FindInText("text|number",qualifiers,re:true,return:'S');~
dtype := TextReplace(dtype,"text","string");~
Local fnDesc := description of (fn);~
Local paramDeclSec := FindInText(RE_for_Parameters_in, Description of (fn), re:true, return:'S');~
Local reParamDesc := RE_for_one_param_des(paramName);~
Local desc := FindInText(reParamDesc, paramDeclSec, subpattern:'desc', return:'S' );~
Local enum := Enum_vals_for_fn_par(fn, paramName); /*to do */~
~
~
Array( Parameters_rec, [ ~
'type':"object",~
'properties':\Array(Param_rec, [dtype, desc, enum]),~
'required':\Subset(bRequired)~
])~
NodeLocation: 288,696,1
NodeSize: 72,24
WindState: 2,384,12,1775,784
Index Parameters_rec
Title: Parameters rec
Definition: ['type','properties','required']
NodeLocation: 120,752,1
NodeSize: 64,24
DisplayOutputs: Object Object, Object Function
Function Remove_null_fields(json)
Title: Remove null fields from json
Description: Remove fields from textual json that have null value.~
{"a":5, "b":null}~
is legal json, but this changes it to~
{"a":5}~
The OpenAI API rejects requests will null fields.
Definition: local json0 := TextReplace(json,"""content""\s*:\s*null","!!!###!!!",all:true, re:true);~
~
Local json1 :=~
TextReplace(~
TextReplace(json0,',\s*"\w+":\s*null','',all:true,re:true),~
'{\s*"\w+":\s*null\s*,?','{',all:true,re:true~
);~
~
TextReplace(json1,"!!!###!!!","""content"":null",all:true)
NodeLocation: 952,408,1
NodeSize: 64,24
WindState: 2,555,191,720,559
Function Enum_vals_for_fn_par( h : handle atom; paramName : text atom)
Title: Enum vals for fn param
Description: Returns a set of enum values for a function parameter, if any, read from the Parameter Enumerations attribute.
Definition: Local decl := ParameterEnumeration of (h);~
if not IsText(decl) then Null Else (~
Local enums := FindInText(f"{paramName}.*?((\R\t[^\r\n]*)+)",~
decl, caseInsensitive:true, re:true, subpattern:1, return:'S');~
Local items := TextTrim(FindInText("\t([^|]*)",enums,return:'S',re:true,~
subpattern:1,repeat:true));~
Local strVal := FindInText("^('(?.*)')|(""(?.*)"")$", items, re:true, return:'S', subpattern:'txt');~
~
items := if strVal=Null then ParseNumber(items,items) else strVal;~
if IsNull(items) then null else \CopyIndex(items)~
)
NodeLocation: 448,696,1
NodeSize: 64,24
WindState: 2,98,82,827,350
DisplayOutputs: Object Object, Object Function
Function API_Functions_Rec(functions : optional ... object)
Title: API Functions Rec
Description: From a function, or collection of functions, return a set describing the functions for the chat API. functions.
Definition: if IsNotSpecified(functions) or size(functions)=0 then null else (~
LocalIndex fn := functions;~
{Remove parameter descriptions from the fn description. These are sent with each parameter}~
Local fnDesc := TextReplace(description of (fn), RE_for_Parameters_in, "", re:true); ~
~
Local params := For f:=slice(functions,@fn) Do ~
\Make_Fn_Params_Rec(f); ~
~
\Array(OpenAI_Function_Item, [~
identifier of (fn), ~
fnDesc, ~
params~
])~
)
NodeLocation: 792,696,1
NodeSize: 64,24
WindState: 2,906,133,968,486
Function ExtractParamNameInds( rec : [Chat_API_field] )
Title: Extract ParamNames indexes
Description: Given a Chat_API record, extract a list of handles to the ParamNames indexes that exist in the function declaration section.
Definition: Local functions := rec[Chat_API_field='functions'];~
if not IsReference(functions) then [] else (~
Local rFnParams[] := (#functions)[OpenAI_Function_Item='parameters'];~
Local props := #(#rFnParams)[Parameters_rec='properties'];~
Handle(props.paramName)~
)
NodeLocation: 616,696,1
NodeSize: 88,24
WindState: 2,98,82,905,428
Function Chat_perform_fn_call( ~
responseChoice : reference atom;~
chatRec : [Chat_API_field] ;~
Chat_index : index~
)
Title: Chat perform fn call
Description: Accepts one completion "choice" from the API's Chat response. This is a reference from the [.Member='choices'] field of the raw response from OpenAI. It returns a «ref» that can replace the original, after performing a function call if the API has ask for a function to be called. If the response is not a function call, the result is the same as the parameter passed.
Definition: Local rec := #responseChoice;~
~
if rec[.Member='finish_reason']<>'function_call' then~
responseChoice~
else (~
Local call := (#(#rec[.Member='message'])[.Member='function_call'])[.Member=Fn_Call_Schema];~
Local fnName := call[Fn_Call_Schema='name'];~
Local fn := HandleFromIdentifier(fnName);~
~
if fn=null then ( ~
Error(f"OpenAI API tried to call {fnName}(...), which doesn't exist in the model.");~
);~
Local args := call[Fn_Call_Schema='arguments'];~
Local parsedArgs := Try( ~
ParseJSON(args),~
catch: { It is inconsistent. args is usually JSON, but sometimes, especially when it ~
hallucinates a python function args is not json, but just text }~
LocalIndex Member := ['expr'] Do Array(Member,[args])~
);~
Local callResult := Perform_callback(fn, parsedArgs, parsedArgs.Member);~
callResult := if IsText(callResult) then callResult else f"{callResult:G}";~
~
Local (nextChatRec, hNextChatIndex) := Chat_rec_for_call_re( chatRec, Chat_index, call, callResult);~
LocalAlias nextChatIndex := hNextChatIndex;~
~
Local raw := Chat_completion_raw0( nextChatRec, nextChatIndex);~
~
Local nextResponseChoice := Slice(#raw[.Member='choices'],1);~
Chat_perform_fn_call(nextResponseChoice, nextChatRec, nextChatIndex )~
)
NodeLocation: 120,568,1
NodeSize: 64,24
WindState: 2,1791,15,1122,1167
Recursive: 1
Function Perform_callback( fn : handle atom ; args :all [ArgName] ; ArgName : Index )
Title: Perform callback
Description: Calls the function with the given parameters, in a name-param calling style (every parameter is named).
Definition: LocalIndex paramNames := SplitText(paramnames of (fn),',');~
Local argOfParam := @[ArgName=paramNames];~
Local positionalArgs :=~
if argOfParam=0 then Undefined else args[@ArgName=argOfParam];~
~
Evaluate(fn,...positionalArgs)
NodeLocation: 432,568,1
NodeSize: 64,24
WindState: 2,131,109,873,466
Function Chat_completion_raw0( chatRec : [Chat_API_field];~
Chat_index : Index ;~
)
Title: Chat completion raw0 response
Description: This returns the next response from in a Chat (ala ChatGPT) given the history of messages so far.~
~
Required parameters:~
«chatRec»: A record representation of a chat and its parameters. Obtained from Function Chat_record(...).~
«Chat_index»: Indexes the sequence of messages in the conversation~
~
Return value:~
The raw parsed json response from the API call.
Definition: Local fns := chatRec[Chat_API_field='functions'];~
Local indOrder := [Handle(Chat_index)];~
If IsReference(fns) then ~
indOrder := Concat(indOrder,[Handle((#fns).fn)]);~
~
Local paramNamesInds := ExtractParamNameInds(chatRec);~
Local objs := Concat(ListOfHandles(Chat_message_field, OpenAI_Function_item, Parameters_rec),~
Concat(paramNamesInds,ListOfHandles(Param_rec,Fn_Call_schema)));~
~
Local json := MakeJSON(chatRec, indexOrder:...indOrder, objects:...objs);~
{ Remove null fields since the API barfs when they are present }~
json := Remove_null_fields(json);~
{ConsolePrint("Send to API"); ConsolePrint(json);}~
Local response := ReadFromURL( OpenAI_Chat_URL, method:'Post', httpHeaders:OpenAI_header_text, httpContent: json );~
{ConsolePrint("Received from API"); ConsolePrint(response );}~
ParseJSON(response)
NodeLocation: 296,408,1
NodeSize: 80,24
WindState: 2,1923,12,1229,1180
Function Chat_rec_for_call_re( origChatRec : [Chat_API_field] ;~
origChatIndex : Index;~
function_call ;~
callResult ~
)
Title: Chat rec for call result
Description: This takes the chatRec before a function callback was requested (i.e., the rec for the API call that requested a fn callback), along with the requested call and the result of the call, and assembles a chatRec that includes the result of the fn callback. This is the parsed version of the JSON that should be sent back to the API for it to continue processing. ~
~
It adds two lines to the messages of the origChatRec.~
~
The caller also needs to know the new chat index. A handle to this is returned as a second return value.
Definition: Local n := IndexLength(origChatIndex);~
Local messages := #origChatRec[Chat_API_field='messages'];~
LocalIndex I / "Chat_index" := 1..n+2;~
Local newMessages := messages[@origChatIndex=I, defVal:null];~
Local fnName := function_call[Fn_Call_schema='name'];~
~
newMessages[ I=n+1 ] := Array( Chat_message_field, [~
"assistant",~
Null,~
Null,~
\function_call ~
]);~
~
newMessages[ I=n+2 ] := Array( Chat_message_field, [~
"function",~
callResult,~
fnName, ~
Null~
]);~
~
Local res := if Chat_API_field='messages' then \newMessages else origChatRec;~
~
MultiResult(~
res,~
Handle(I)~
)
NodeLocation: 288,568,1
NodeSize: 64,24
WindState: 2,306,69,1066,989
Index Fn_Call_schema
Title: Fn Call schema
Definition: ['name','arguments']
NodeLocation: 1008,208,1
NodeSize: 64,24
Constant OpenAI_Image_Gen_URL
Title: OpenAI Image Gen URL
Definition: 'https://api.openai.com/v1/images/generations'
NodeLocation: 96,864,1
NodeSize: 64,24
Constant OpenAI_max_images
Title: OpenAI max images at a time
Definition: 10
NodeLocation: 248,864,1
NodeSize: 64,32
Index OA_Image_query_rec
Title: OA Image query rec
Definition: ['prompt','n','size','response_format','user']
NodeLocation: 408,864,1
NodeSize: 64,24
Function Make_image_rec( prompt ; n : positive atom ; size : text orNull atom )
Title: Make image rec
Description: Returns query record for an image query.~
«prompt» should be either a since text or a 1-D list.
Definition: Table(OA_Image_query_rec)(RefIfArray(prompt),n,size,'url',GetProcessInfo('UserName'))
NodeLocation: 568,864,1
NodeSize: 64,24
WindState: 2,589,831,720,350
DefnState: 2,96,555,1025,484,0,DFNM
Function RefIfArray(x)
Title: RefIfArray
Description: Returns x when x is a scalar, or \x when x is a list or array.
Definition: if Size(IndexesOf(x))=0 then x else \x
NodeLocation: 728,864,1
NodeSize: 64,24
Constant RE_for_Parameters_in
Title: RE for Parameters in Description
Definition: Local oneParamDesc := RE_for_one_param_des("\w+?");~
f"Parameters:?\s*\R([•*«\t][^\r\n]*\R)+"
NodeLocation: 1336,112,1
NodeSize: 64,32
ValueState: 2,484,490,1121,293,,MIDM
DisplayOutputs: Object Object, Object Function
Function RE_for_one_param_des(name)
Title: RE for one param desc
Description: A regular expression for parsing the description of a single parameter with the given name from within a full Description. It looks for a line having one of these forms, each preceded by a newline:~
~
* name: description~
• name: description~
«name»: description~
* «name»: description~
• «name»: description~
~
When the description of the parameter has more than one line, it expects each subsequent line to be tab-indented (i.e., the first character must be a tab character).~
~
The subpattern "desc" contains the full description, the subpattern "start" has the first line only, and the subpattern "rest" has the remaining lines, each tab indented. Typical usage:~
~
FindInText( RE_for_one_param_des("x"), description of F, return:'S', subpattern:'desc' )~
Definition: Local bulletName := f"(?:[•|*]\s*{name})";~
Local nonBulletName := f"(?:«{name}»)";~
Local bothName := f"(?:[•|*]\s*«{name}»)";~
Local lineStart := "\R";~
Local nameDecl := f"{lineStart}({bulletName}|{nonBulletName}|{bothName}):\s*";~
Local start := "(?[^\r\n]*)"; { The first line of the description }~
Local indentedLine := "(?:\R\t+[^\r\n]+)";~
f"{nameDecl}(?{start}(?{indentedLine}*))";~
NodeLocation: 1344,200,1
NodeSize: 64,24
WindState: 2,31,92,720,571
Function python( expr : text)
Description: GPT seems to hallucinate the existance of a function named python, which apparently is supposed to evaluate a python expression. This function handles such calls. GPT sometimes does this to perform arithmetic, so in some cases we might be able to process these fairly simply.~
~
Attempts to evaluate simple expressions that transform obviously to Analytica expressions. More complex expressions will fail, and then it reports that there is no function named python.
Definition: Local adj_expr := TextReplace(expr, ~
"(?\w+)\s*=(?[^\r\n]+(\R[\t\s]+[^\r\n]*)*)",~
"Local :=;",~
all:true, re:true );~
adj_expr := TextReplace(adj_expr,"**","^",all:true);~
Local result := Evaluate(adj_expr);~
if result=null ~
then "Error: There is no function named python. But do not appologize for this error."~
else result
NodeLocation: 584,568,1
NodeSize: 64,24
WindState: 2,1325,75,720,639
Close Open_AI_lib_internal
Library Similarity_embedding
Title: Similarity embeddings
Description:
Author: Lonnie Chrisman~
Lumina Decision Systems
Date: Thu, Jul 20, 2023 3:17 PM
NodeLocation: 1032,144,1
NodeSize: 80,24
DiagState: 2,257,97,1278,598,17,10
Function Embedding_similarity( x,y : [ Ada_embedding] )
Title: Embedding similarity
Description: Returns the similarity between two text embeddings (obtained using the Embedding_for function).
Definition: Sum(x*y, Ada_embedding )
NodeLocation: 960,72,1
NodeSize: 64,24
WindState: 2,504,428,720,350
DisplayOutputs: Object Object, Object Variable
Function Embedding_for( txt : text orNull )
Title: Embedding for
Description: Returns the embedding for some txt. When an array of text is passed in, the embeddings are obtained in a single call to the OpenAI UI.~
~
This also returns the number of prompt tokens in the request (2nd return value) and the total tokens (3rd return value).
Definition: Local json := Embedding_resp_json(txt);~
Local inds := indexesOf(txt);~
Local flat_embeddings := ~
Local r[] := #json[.Member='data'] Do~
Slice(#(#r)[.Member='embedding'],@Ada_embedding);~
Local usage := #json[.Member='usage'];~
Local unflat := Unflatten(flat_embeddings, , ResultIndexes:...inds);~
unflat := if size(inds)=0 then Slice(unflat,1) else unflat;~
MultiResult(~
if txt=null then null else unflat,~
usage[.Member='prompt_tokens'],~
usage[.Member='total_tokens']~
)
NodeLocation: 816,72,1
NodeSize: 64,24
WindState: 2,565,53,932,561
DisplayOutputs: Object Object, Object Variable
Module Ex_Open_AI_Lib
Title: Examples
Author: Lonnie Chrisman~
Lumina Decision Systems
Date: Thu, Jul 20, 2023 3:17 PM
NodeLocation: 816,152,1
NodeSize: 72,24
DiagState: 2,716,131,1100,421,17,10
Variable Ex_OAL_To_Encode
Title: Array of text
Definition: Table(Ex_OAL_I,Ex_OAL_J)(~
'hello','there',~
'world',Null,~
'and','bar')
NodeLocation: 296,80,1
NodeSize: 64,24
ValueState: 2,1936,732,416,303,,MIDM
Variable Embeddings_for_text
Title: Embeddings for text
Definition: Local (emb,promptTokens,totalTokens) := Embedding_for(Ex_OAL_To_Encode); ~
ConsolePrint(f"prompt tokens={promptTokens}, total tokens={totalTokens}");~
emb
NodeLocation: 296,160,1
NodeSize: 64,24
ValueState: 2,953,118,892,606,,MIDM
ReformVal: [Ada_embedding,Sys_LocalIndex('I')]
Att_ResultSliceState: [Ex_OAL_J,1,Ex_OAL_I,1,Ada_embedding,1]
Variable Ex_OAL_Test_List
Title: Embeddings for List of Text
Definition: Embedding_for(['hello','world'])
NodeLocation: 472,160,1
NodeSize: 72,24
Variable Test_scalar_text_emb
Title: Test scalar text embeding
Definition: Embedding_for('How is the time')
NodeLocation: 472,80,1
NodeSize: 72,24
ValueState: 2,68,74,816,279,,MIDM
Index Ex_OAL_I
Title: I
Definition: 1..3
NodeLocation: 112,72,1
NodeSize: 64,24
Index Ex_OAL_J
Title: J
Definition: 'j'&(1..2)
NodeLocation: 112,136,1
NodeSize: 64,24
Index Ex_OAL_Rec
Att_PrevIndexValue: ['Abraham Lincoln''s Gettysburg Address (1863)','Franklin D. Roosevelt''s First Inaugural Address (1933)','John F. Kennedy''s Inaugural Address (1961)','Lyndon B. Johnson''s ''We Shall Overcome'' Speech (1965)','Ronald Reagan''s ''Tear Down This Wall'' Speech (1987)']
Title: Speech name
Definition: ["Abraham Lincoln's Gettysburg Address (1863)","Franklin D. Roosevelt's First Inaugural Address (1933)","John F. Kennedy's Inaugural Address (1961)","Lyndon B. Johnson's 'We Shall Overcome' Speech (1965)","Ronald Reagan's 'Tear Down This Wall' Speech (1987)"]
NodeLocation: 112,256,1
NodeSize: 64,24
Variable Ex_OAL_Ref_Material
Title: Presidential speech
Definition: Table(Ex_OAL_Rec)('Four score and seven years ago our fathers brought forth on this continent, a new nation, conceived in Liberty, and dedicated to the proposition that all men are created equal.','I am certain that my fellow Americans expect that on my induction into the Presidency I will address them with a candor and a decision which the present situation of our Nation impels. This is preeminently the time to speak the truth, the whole truth, frankly and boldly. Nor need we shrink from honestly facing conditions in our country today. This great Nation will endure as it has endured, will revive and will prosper.','We observe today not a victory of party, but a celebration of freedom—symbolizing an end, as well as a beginning—signifying renewal, as well as change. For I have sworn before you and Almighty God the same solemn oath our forebears prescribed nearly a century and three quarters ago.','I speak tonight for the dignity of man and the destiny of democracy. I urge every member of both parties, Americans of all religions and of all colors, from every section of this country, to join me in that cause.','Chancellor Kohl, Governing Mayor Diepgen, ladies and gentlemen: Twenty-four years ago, President John F. Kennedy visited Berlin, speaking to the people of this city and the world at the City Hall. Well, since then two other presidents have come, each in his turn, to Berlin. And today I, myself, make my second visit to your city.')
NodeLocation: 112,320,1
NodeSize: 64,24
DefnState: 2,280,96,1233,433,0,DFNM
{!40700|Att_CellFormat: CellFormats(CellEntry(0,0,1,0,0),CellFont('Calibri'),CellAlignment('Left'))}
Decision EX_OAL_Search_query
Title: Search queries
Definition: ['Racial injustice','References to religion','Berlin, Germany','Americans should join together','87','Creating a new country','Our country will survive','To tell the truth','To face reality']
NodeLocation: 112,384,1
NodeSize: 64,24
Variable Ex_OAL_Speech_embedd
Title: Speech embeddings
Definition: Embedding_for(Ex_OAL_Ref_Material)
NodeLocation: 296,280,1
NodeSize: 72,24
ValueState: 2,324,330,1240,303,,MIDM
Variable Ex_OAL_Query_emb
Title: Query embedding
Definition: Embedding_for(EX_OAL_Search_query)
NodeLocation: 296,360,1
NodeSize: 64,24
Variable Ex_OAL_Similarity_sp
Title: Similarity of query to speech
Definition: Embedding_similarity(Ex_OAL_Speech_embedd,Ex_OAL_Query_emb)
NodeLocation: 520,288,1
NodeSize: 80,24
ValueState: 2,704,165,645,470,1,MIDM
GraphSetup: Flip:8~
Att_GraphValueRange Ex_OAL_Similarity_sp:1,,,0,1
ReformVal: [Ex_OAL_Rec,EX_OAL_Search_query]
Att_ResultSliceState: [EX_OAL_Search_query,1,EX_OAL_Search_query,2,Ex_OAL_Rec,1]
Att_ColorRole: Null
{!40600|Att_ClusterIndex: Null}
Close Ex_Open_AI_Lib
Text Te1936903827
Title: About similarity embeddings
Description: ~
Similarity embeddings are used for finding the text records that are most similar in meaning to a given text. An embedding is a vector that represents the meaning of a block of text, and by computing the similarity between two vectors you arrive at a measure of how much the original text strings deal with the same topic.~
~
For example, you might want to find a small set of web pages that most closely matches a search query. You could store the encodings for small blocks of text that appear on each web page, and then find the blocks of text with the highest similarity to the search query.~
~
In the Examples module, take a look at the "Similarity of query to speech", which matches a query with text from the first paragraph of 5 famous US presidential speeches. Notice how the match doesn't require the words or phrases to be the same. For example, the query "87" strongly matches Lincoln's "Four score and seven years ago..."~
~
The two main functions are:~
• Embedding_for( text ): Returns the embedding vector for text.~
• Embedding_similarity( X, Y ): Returns the similarity between two embedding vectors.~
~
Let Embedding_similarity(X,Y) array abstract to measure similarity across a collection.~
~
Note that an embedding vector will always be indexed by Ada_embedding -- this is the embedding dimension for the Ada model, OpenAI's model that is tuned for doing embeddings efficiently.
NodeLocation: 376,280,-1
NodeSize: 304,240
NodeInfo: 1,,,,1,1
NodeColor: 52427,60621,65535
Close Similarity_embedding
Alias Al125226643
Title: OpenAI Model Name
NodeLocation: 1216,56,1
NodeSize: 64,24
Original: OpenAI_Model_Name
Library OAL_Text_completions
Title: Text completions
Description:
Author: Lonnie Chrisman~
Lumina Decision Systems
Date: Fri, Jul 21, 2023 1:48 PM
NodeLocation: 1032,224,1
NodeSize: 80,24
DiagState: 2,1282,23,1125,753,17,10
Function Chat_completion( messages : text all [Chat_index] ;~
role : text [Chat_index] ;~
Chat_index : Index ;~
~
modelName : text atom = 'gpt-3.5-turbo' ;~
~
functions : optional ... Object;~
~
temperature : optional NonNegative atom ;~
top_p : optional positive atom ;~
~
Completion_index : optional Index ;~
stop_sequences : optional text ;~
~
max_tokens : optional atom ;~
presence_penalty, frequency_penalty : optional number atom ~
)
Title: Chat completion
Description: This returns the next response from in a Chat (ala ChatGPT) given the history of messages so far.~
~
Required parameters:~
«messages» : The sequence of messages so far, in order, indexed by «Chat_index».~
«role» : Each message has a role, which must be one of 'system', 'user', 'assistant', or 'function'.~
«Chat_index»: Indexes the sequence of messages in the conversation~
~
Return values:~
1. The main return value is the textual response (the content). ~
If «Completion_index» is specified, this is a set of completions indexed by «Completion_index».~
2. The finish_reason. Usually Null, but may be "stop" if a stop_sequence is encountered.~
3. Number of prompt tokens. This is the total number in all the messages.~
4. Number of tokens in the completion.~
5. A reference to the full parsed response from the server.~
~
Optional parameters:~
«modelName»: The OpenAI model to use. It must support Chat. 'gpt-3.5', 'gpt-3.5-turbo' and 'gpt-4' are common choices.~
«functions» : One or more functions that the LLM can call during its completions.~
«temperature»: A value between 0 and 2. ~
Smaller values are more focused and deterministic, Higher values are more random. Default=1.~
«top_p»: A value 0