remark -- indent-tabs-mode: nil; -- }

The Purpose of Keyword Syntax

Keyword syntax offers an elegant way to write queries with Allegrograph Magic Predicates, when the predicate has a large and unwieldy number of variables, while maintaining compatibility with standard SPARQL syntax.

Currently these three LLM magic predicates accept keyword syntax: llm:nearestNeighbor, llm:askMyDocuments and llm:chatState.

And the SNA magic property sna:communityLeiden accepts keywords as well.

Here is how keywords work with magic predicates. The syntax provided for the magic predicate llm:nearestNeigbor is

(?uri ?score ?originalText ?pred ?type) llm:nearestNeighbor (?text ?vectorRepoSpec ?topN ?minScore ?selector ?useClustering) 

In this form, the variables are called positional because the values must appear in the specified position, e.g. ?uri in the first position, ?score in the second, and so on. Any optional variables may be omitted, but processing any one of them requires specifying all the variables to the left of it. (Note: the ?selector and the ?useClustering arguments reduce the search space and so speed up the queries. ?selector is documented here. ?userClustering will use clusters within the repo if they have been created. See the description of creating clusters in a repo here.

We know from the documentation, that only two of the input variables (on the right) and one of the output variables (on the left) are required and the rest are optional. The minimal form for this predicate is:

?uri llm:nearestNeighbor (?text ?vectorRepoSpec) 

This form is fine if we only care about the required variables. However suppose we only care about the setting the optional input ?selector and the reading optional output ?originalText. The positional syntax required a query to use an expression like

(?uri ?score ?originalText) llm:nearestNeighbor (?text ?vectorRepoSpec ?topN ?minScore ?selector) 

where all the positional arguments, up to the ones we care about, must be specified in order, even if we are willing to leave those values (?score in output and ?topN and ?minScore in input) unspecified.

The new keyword syntax allows us to write

(?uri :originalText ?originalText) llm:nearestNeighbor (?text :selector ?selector :vectorRepoSpec ?vectorRepoSpec) 

thus ignoring the output variable ?score and accepting the default values of ?topN and ?minScore. Note also that the keyword syntax permits the arguments to appear in any order.

How Keyword Syntax Works

When Allegrograph evaluates a magic predicate within a SPARQL query, the input variables are evaluated and the output variables are bound

Whether bound or evaluated, the keyword-enabled magic predicates process variables in the same order: from left to right, treating each as a positional variable until a keyword is found. Once the left-to-right process finds a keyword, the remaining variables are expected to be given in keyword syntax. Thus, to continue with the nearestNeighbor example, in the expression

(?uri :originalText ?originalText) llm:nearestNeighbor (?text :vectorRepoSpec ?vectorRepoSpec :selector ?selector) 

the process detects ?uri and ?text as positional syntax, and ?originalText, ?vectorRepoSpec and ?selector as keyword syntax.

However the following form is invalid:

(?uri :originalText ?originalText) llm:nearestNeighbor (?text :vectorRepoSpec ?vectorRepoSpec ?topN ?minScore ?selector) 

because after the process identifies ?vectorRepoSpec as keyword syntax, it expects the remaining variables on the right be to in keyword syntax.

A Note on Namespaces

One detail we've glossed over so far, is the way SPARQL interprets a keyword like :key. In order to make the token :key compatible with SPARQL syntax, we have to bind the empty namespace : to a special keyword namespace, as in the SPARQL statement

PREFIX : <http://franz.com/ns/keyword#> 

In Allegrograph, the default value of the empty namespace is (link http://franz.com/ns/keyword#), so in most cases a keyword can be abbreviated like :kw. But if the environment binds the empty namespace to something else (which is actually not uncommon) then users wanting to use the keyword syntax should bind a different prefix, such as key, as follows:

PREFIX kw: <http://franz.com/ns/keyword#> 

and then you can write the example above as:

(?uri kw:text ?originalText) llm:nearestNeighbor (?text kw:vectorRepoSpec ?vectorRepoSpec kw:selector ?selector) 

Examples Using Keyword Syntax

Some examples may help explain the keyword syntax.

In these examples, assume we have a vector store historicalVec containing an indexed embeddings of names of famous historical figures.

Suppose we are interested in the matching original text, but not the score:

SELECT * {  
  (?uri :originalText ?originalText) llm:nearestNeighbor ("Abraham Lincoln" "historicalVec" 10 0.0)  
} 

Here we set the minimum matching score, but accept the default value for the top N matches:

SELECT * {  
  (?uri :originalText ?originalText) llm:nearestNeighbor ("Abraham Lincoln" "historicalVec" :minScore 0.8)  
} 

In this case we specify all the optional input variables using keyword syntax:

SELECT * {  
  (?uri ?score ?originalText) llm:nearestNeighbor ("Abraham Lincoln" "historicalVec" :topN 10 :minScore 0.0 :selector "{?id rdf:type <http://franz.com/vdb/gen/Object>}")  
} 

It is even possible to place required positional arguments out-of-order using keyword syntax, as in this example where we reverse the order of the output arguments:

SELECT * {  
  (:originalText ?originalText :score ?score :uri ?uri) llm:nearestNeighbor ("Abraham Lincoln" "historicalVec")  
} 

For completeness, this last example illustrates using keyword syntax with every variable:

PREFIX llm: <http://franz.com/ns/allegrograph/8.0.0/llm/>  
SELECT * {  
  (:uri ?uri :score ?score :originalText ?text :pred ?pred :type ?type)  
  llm:nearestNeighbor  
  (:text "Abraham Lincoln" :vectorRepoSpec "historicalVec" :topN 10 :minScore 0.8 :selector "{?id rdf:type <http://franz.com/vdb/gen/Object>.}")  
} 

LLM Predicates Accepting Keyword Syntax

The LLM magic predicates and llm:nearestNeighbor, llm:askMyDocuments, and llm:chatState. (sna:communityLeiden also accepts keywords but is not discussed in this section.)

The following tables summarizes all the keyword arguments for the three predicates.

For an explanation of the :selector argument to llm:nearestNeighbor and llm:askMyDocuments, see the Documentation for selector.

For information on creating clusters to use with the :useClustering argument, see this discussion of creating clusters.

First llm:nearestNeighbor:

Variable Role nearestNeighbor Keyword Optional Variable? nearestNeighbor Variable Description
Output Variables:
Output :score No Match score
Output :uri Yes ID of matching text
Output :originalText Yes ID of matching text
Output :pred Yes Predicate associated with embedded object
Output :type Yes Type of subject associated with embedded object
Input Variables:
Input :text No Input text string
Input :vectorRepoSpec No Vector store repo spec
Input :topN Yes Maximum number of matches
Input :minScore Yes Minimum score for matches
Input :selector Yes Selects subsets of vector repo
Input :useClustering Yes Causes a clustering created by agtool to be used, see above for more information.

Second, keyword arguments to llm:askMyDocuments:

Variable Role askMyDocuments Keyword Optional Variable? askMyDocuments Variable Description
Output Variables:
Output :response No LLM Response text
Output :score No Match score
Output :citationId Yes ID of matching text
Output :citedText Yes Matching text
Input Variables:
Input :text No Input text string
Input :vectorRepoSpec No Vector store repo spec
Input :topN Yes Maximum number of matches
Input :minScore Yes Minimum score for matches
Input :selector Yes Selects subsets of vector repo
Input :useClustering Yes Causes a clustering created by agtool to be used, see above for more information.

Finally, keyword arguments to llm:chatState:

Variable Role chatState Keyword Optional Variable? chatState Variable Description
Output Variables:
Output :response No LLM Response text
Output :score No Match score
Output :citationId Yes ID of matching text
Output :citedText Yes Matching text
Output :citationSource Yes Source vector store of match
Output :feed Yes Recent dialog exchanges
Output :story Yes Statement about feed
Output :expertiseMatchString Yes Match string for Expertise repo
Output :expertiseMatches Yes Matching Expertise embeddings and IDs
Output :expertiseHints Yes Statement about matching expertise
Output :historyMatchString Yes Match string for History repo
Output :historyMatches Yes Matching history embeddings and IDs
Output :historyHints Yes Statement about matching history
Output :prompt Yes Prompt for LLM
Input Variables:
Input :text No Input text string
Input :expertiseRepoSpec No Expertise vector repo spec
Input :expertiseTopN Yes Maximum number of Expertise matches
Input :expertiseMinScore Yes Minimum score for Expertise matches
Input :historyTopN Yes Maximum number of History matches
Input :historyMinScore Yes Minimum score for History matches
Input :botId Yes ID of bot
Input :historyRepoSpec Yes History vector repo spec
Input :useClustering Yes Causes a clustering created by agtool to be used, see above for more information.