Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
pberlandier committed Aug 1, 2024
0 parents commit 74dc9b7
Show file tree
Hide file tree
Showing 41 changed files with 846 additions and 0 deletions.
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# watsonx.ai invocation from ODM

This repo provides a Java XOM library (see `watsonx-helper` [Maven project](./watsonx-helper)) to support the invocation of a watsonx.ai inference from ODM rules.

The `WatsonxAIRunner.java` class allows to:

- Store the different parameters for the LLM invocation (prompt template, prompt variables and model parameters). Most of the model parameters are associated with a default value.
- Run a *[watsonx.ai](https://www.ibm.com/products/watsonx-ai)* inference using the above parameters, the watsonx.ai instance URL and the API key for this instance.

The class is verbalized in the `watsonx-model` BOM entry in the rule project, allowing to:

- Define the prompt template to be executed and the prompt variables. Below is an example of parameters setup:

![](./doc/initialize.png)

- Execute the inference on the parameters:

![](./doc/run.png)

## Simple use case

The simple use case for testing is about deciding how to dispose from a customer review, either publish it if the review is positive or ignore it if it's negative.

- The ODM input provides the customer review text.
- A simple sentiment extraction prompt template return either `positive` or `negative` as a result.
- ODM passes the prompt template instantiated with the review text to the LLM.
- The LLM response is mapped to an enumeration and used in a decision table to decide how to dispose of the review.

### Sample execution

- Run `mvn install package` in the `watsonx-helper` folder to compile and package the the uber jar used for the ODM XOM.
- Run the `reviewDisposition` decision operation to test the rules.
6 changes: 6 additions & 0 deletions customer-review-rules/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/output/
/reports/
/target/
.syncEntries
*.log

21 changes: 21 additions & 0 deletions customer-review-rules/.project
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>customer-review-rules</name>
<comment></comment>
<projects>
<project>customer-review-xom</project>
<project>watsonx-helper</project>
</projects>
<buildSpec>
<buildCommand>
<name>ilog.rules.studio.model.ruleBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>ilog.rules.studio.model.decisionProject</nature>
<nature>ilog.rules.studio.model.operationProject</nature>
<nature>ilog.rules.studio.model.ruleNature</nature>
</natures>
</projectDescription>
34 changes: 34 additions & 0 deletions customer-review-rules/.ruleproject
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<ilog.rules.studio.model.base:RuleProject xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:com.ibm.rules.studio.model.decisionservice="http://com.ibm.rules.studio/model/decisionservice.ecore" xmlns:ilog.rules.studio.model.base="http://ilog.rules.studio/model/base.ecore" xmlns:ilog.rules.studio.model.bom="http://ilog.rules.studio/model/bom.ecore" xmlns:ilog.rules.studio.model.query="http://ilog.rules.studio/model/query.ecore" xmlns:ilog.rules.studio.model.rule="http://ilog.rules.studio/model/rule.ecore" xmlns:ilog.rules.studio.model.xom="http://ilog.rules.studio/model/xom.ecore" buildMode="DecisionEngine" isADecisionService="true" migrationFlag="3">
<name>customer-review-rules</name>
<uuid>cda5c0a0-a970-438d-8ef5-bcf36759227d</uuid>
<outputLocation>output</outputLocation>
<categories>any</categories>
<paths xsi:type="ilog.rules.studio.model.xom:XOMPath" pathID="XOM">
<entries xsi:type="ilog.rules.studio.model.xom:LibraryXOMPathEntry" name="org.eclipse.jdt.launching.JRE_CONTAINER" url="file:org.eclipse.jdt.launching.JRE_CONTAINER" kind="LIBRARY" exported="false"/>
<entries xsi:type="ilog.rules.studio.model.xom:SystemXOMPathEntry" name="customer-review-xom" url="platform:/customer-review-xom" kind="JAVA_PROJECT" exported="true"/>
<entries xsi:type="ilog.rules.studio.model.xom:SystemXOMPathEntry" name="watsonx-helper-0.0.1-SNAPSHOT-jar-with-dependencies.jar" url="platform:/watsonx-helper/target/watsonx-helper-0.0.1-SNAPSHOT-jar-with-dependencies.jar" exported="true"/>
</paths>
<paths xsi:type="ilog.rules.studio.model.bom:BOMPath" pathID="BOM">
<entries xsi:type="ilog.rules.studio.model.bom:BOMEntry" name="model" url="platform:/customer-review-rules/bom/model.bom" origin="xom:/customer-review-rules//customer-review-xom"/>
<entries xsi:type="ilog.rules.studio.model.bom:BOMEntry" name="watsonxai-model" url="platform:/customer-review-rules/bom/watsonxai-model.bom" origin="xom:/customer-review-rules//watsonx-helper/target/watsonx-helper-0.0.1-SNAPSHOT-jar-with-dependencies.jar"/>
</paths>
<modelFolders xsi:type="ilog.rules.studio.model.base:SourceFolder">
<name>rules</name>
</modelFolders>
<modelFolders xsi:type="ilog.rules.studio.model.bom:BOMFolder">
<name>bom</name>
</modelFolders>
<modelFolders xsi:type="ilog.rules.studio.model.rule:TemplateFolder">
<name>templates</name>
</modelFolders>
<modelFolders xsi:type="ilog.rules.studio.model.query:QueryFolder">
<name>queries</name>
</modelFolders>
<modelFolders xsi:type="ilog.rules.studio.model.base:ResourceFolder">
<name>resources</name>
</modelFolders>
<modelFolders xsi:type="com.ibm.rules.studio.model.decisionservice:OperationFolder">
<name>deployment</name>
</modelFolders>
</ilog.rules.studio.model.base:RuleProject>
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
eclipse.preferences.version=1
encoding/<project>=UTF-8
4 changes: 4 additions & 0 deletions customer-review-rules/bom/model.b2xa
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<b2x:translation xmlns:b2x="http://schemas.ilog.com/JRules/1.3/Translation" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schemas.ilog.com/JRules/1.3/Translation ilog/rules/schemas/1_3/b2x.xsd">
<id>f18d3b81-5807-4a4b-a747-b2dfdf2282f7</id>
<lang>ARL</lang>
</b2x:translation>
27 changes: 27 additions & 0 deletions customer-review-rules/bom/model.bom
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@

property loadGetterSetterAsProperties "true"
property origin "xom:/customer-review-rules//customer-review-xom"
property uuid "38546ac7-6c6a-4a3c-9480-0e3cbd97444a"
package com.acme;


public class CustomerReview
{
public string content;
public string disposition;
public com.acme.Sentiment sentiment;
public CustomerReview();
}

public final class Sentiment
extends java.lang.Enum
{
domain {static POSITIVE, static NEGATIVE, static UNKNOWN}
public static final readonly com.acme.Sentiment NEGATIVE;
public static final readonly com.acme.Sentiment POSITIVE;
public static final readonly com.acme.Sentiment UNKNOWN;
public static com.acme.Sentiment map(string arg);
public static com.acme.Sentiment valueOf(string arg);
public static com.acme.Sentiment[] values();
}

18 changes: 18 additions & 0 deletions customer-review-rules/bom/model_en_US.voc
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Vocabulary Properties
uuid = 89f73776-9a7a-45f0-b1f6-78680765eddc

# com.acme.CustomerReview
com.acme.CustomerReview#concept.label = customer review
com.acme.CustomerReview.content#phrase.action = set the content of {this} to {content}
com.acme.CustomerReview.content#phrase.navigation = {content} of {this}
com.acme.CustomerReview.disposition#phrase.action = set the disposition of {this} to {disposition}
com.acme.CustomerReview.disposition#phrase.navigation = {disposition} of {this}
com.acme.CustomerReview.sentiment#phrase.action = set the sentiment of {this} to {sentiment}
com.acme.CustomerReview.sentiment#phrase.navigation = {sentiment} of {this}

# com.acme.Sentiment
com.acme.Sentiment#concept.label = sentiment
com.acme.Sentiment.NEGATIVE#instance.label = NEGATIVE
com.acme.Sentiment.POSITIVE#instance.label = POSITIVE
com.acme.Sentiment.UNKNOWN#instance.label = UNKNOWN
com.acme.Sentiment.map(java.lang.String)#phrase.navigation = the sentiment from {0}
13 changes: 13 additions & 0 deletions customer-review-rules/bom/watsonxai-model.b2xa
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<b2x:translation xmlns:b2x="http://schemas.ilog.com/JRules/1.3/Translation" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schemas.ilog.com/JRules/1.3/Translation ilog/rules/schemas/1_3/b2x.xsd">
<id>eb9513a8-1d8f-47dd-b6c6-c8870926f296</id>
<lang>ARL</lang>
<class>
<businessName>com.ibm.odm.WatsonxAIRunner</businessName>
<method>
<name>runInference</name>
<body language="arl"><![CDATA[
this.runInference(url, apikey, true);
]]></body>
</method>
</class>
</b2x:translation>
29 changes: 29 additions & 0 deletions customer-review-rules/bom/watsonxai-model.bom
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@

property loadGetterSetterAsProperties "true"
property origin "xom:/customer-review-rules//watsonx-helper/target/watsonx-helper-0.0.1-SNAPSHOT-jar-with-dependencies.jar"
property uuid "a3fcf3a1-4d7c-44de-a5f4-9dd19f08192f"
package com.ibm.odm;


public class WatsonxAIRunner
{
public string decodingMethod;
public readonly boolean error;
public readonly boolean exception;
public readonly string input;
public int maxNewTokens;
public readonly string message;
public int minNewTokens;
public string modelId;
public readonly string output;
public string projectId;
public string promptTemplate;
public int repetitionPenalty;
public readonly boolean valid;
public WatsonxAIRunner();
public void addVariable(string arg1, string arg2);
public void clearVariables();
public void runInference(string arg1, string arg2, boolean arg3);
public void runInference();
}

28 changes: 28 additions & 0 deletions customer-review-rules/bom/watsonxai-model_en_US.voc
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Vocabulary Properties
uuid = 9d1885f5-be1e-4415-a929-b7d873ed6d0f

# com.ibm.odm.WatsonxAIRunner
com.ibm.odm.WatsonxAIRunner#concept.label = watsonx.ai runner
com.ibm.odm.WatsonxAIRunner.addVariable(java.lang.String,java.lang.String)#phrase.action = add variable [{0} = {1}] to {this}
com.ibm.odm.WatsonxAIRunner.clearVariables()#phrase.action = clear the variables of {this}
com.ibm.odm.WatsonxAIRunner.decodingMethod#phrase.action = set the decoding method of {this} to {decoding method}
com.ibm.odm.WatsonxAIRunner.decodingMethod#phrase.navigation = {decoding method} of {this}
com.ibm.odm.WatsonxAIRunner.error#phrase.navigation = {this} is error
com.ibm.odm.WatsonxAIRunner.exception#phrase.navigation = {this} is exception
com.ibm.odm.WatsonxAIRunner.input#phrase.navigation = {input} of {this}
com.ibm.odm.WatsonxAIRunner.maxNewTokens#phrase.action = set the max new tokens of {this} to {max new tokens}
com.ibm.odm.WatsonxAIRunner.maxNewTokens#phrase.navigation = {max new tokens} of {this}
com.ibm.odm.WatsonxAIRunner.message#phrase.navigation = {message} of {this}
com.ibm.odm.WatsonxAIRunner.minNewTokens#phrase.action = set the min new tokens of {this} to {min new tokens}
com.ibm.odm.WatsonxAIRunner.minNewTokens#phrase.navigation = {min new tokens} of {this}
com.ibm.odm.WatsonxAIRunner.modelId#phrase.action = set the model id of {this} to {model id}
com.ibm.odm.WatsonxAIRunner.modelId#phrase.navigation = {model id} of {this}
com.ibm.odm.WatsonxAIRunner.output#phrase.navigation = {output} of {this}
com.ibm.odm.WatsonxAIRunner.projectId#phrase.action = set the project id of {this} to {project id}
com.ibm.odm.WatsonxAIRunner.projectId#phrase.navigation = {project id} of {this}
com.ibm.odm.WatsonxAIRunner.promptTemplate#phrase.action = set the prompt template of {this} to {prompt template}
com.ibm.odm.WatsonxAIRunner.promptTemplate#phrase.navigation = {prompt template} of {this}
com.ibm.odm.WatsonxAIRunner.repetitionPenalty#phrase.action = set the repetition penalty of {this} to {repetition penalty}
com.ibm.odm.WatsonxAIRunner.repetitionPenalty#phrase.navigation = {repetition penalty} of {this}
com.ibm.odm.WatsonxAIRunner.runInference()#phrase.action = run inference on {this}
com.ibm.odm.WatsonxAIRunner.valid#phrase.navigation = the invocation of {this} was successful
11 changes: 11 additions & 0 deletions customer-review-rules/deployment/analyzeCustomerReview.dop
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<com.ibm.rules.studio.model.decisionservice:Operation xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:com.ibm.rules.studio.model.decisionservice="http://com.ibm.rules.studio/model/decisionservice.ecore" xmlns:ilog.rules.studio.model.query.extractor="http://ilog.rules.studio/model/query/extractor.ecore" rulesetName="analyzeCustomerReview" usingRuleflow="true" ruleflowName="analyze customer review" targetRuleProjectName="customer-review-rules">
<name>analyzeCustomerReview</name>
<uuid>1f521a98-f1c0-4bfb-b5c7-3e14f883fd2c</uuid>
<referencedVariables variableName="review" variableSetName="decision parameters" direction="IN_OUT">
<variableSet href="../rules/decision%20parameters.var#b8312ee5-0dc4-44ab-9f26-bf2f2efbb1f3"/>
</referencedVariables>
<ruleflow href="../rules/analyze%20customer%20review.rfl#d86dd55d-ec54-4c9e-b6fc-9013921f0343"/>
<extractor xsi:type="ilog.rules.studio.model.query.extractor:QueryExtractor" name="reviewDisposition_extractor" validator="Default Validator"/>
<targetRuleProject href="../../customer-review-rules#cda5c0a0-a970-438d-8ef5-bcf36759227d"/>
</com.ibm.rules.studio.model.decisionservice:Operation>
Binary file not shown.
Binary file not shown.
77 changes: 77 additions & 0 deletions customer-review-rules/rules/analyze customer review.rfl
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
<ilog.rules.studio.model.ruleflow:RuleFlow xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:ilog.rules.studio.model.ruleflow="http://ilog.rules.studio/model/ruleflow.ecore">
<name>analyze customer review</name>
<uuid>d86dd55d-ec54-4c9e-b6fc-9013921f0343</uuid>
<locale>en_US</locale>
<categories>any</categories>
<rfModel>
<Ruleflow xmlns="http://schemas.ilog.com/Rules/7.0/Ruleflow">
<Body>
<TaskList>
<StartTask Identifier="task_0"/>
<RuleTask ExecutionMode="Fastpath" ExitCriteria="None" Identifier="determine review sentiment" Ordering="Literal">
<RuleList>
<Rule Uuid="1754707d-4258-4b65-b759-0fbdf0e4d730"/>
<Rule Uuid="7cdfa6cd-5389-4ef1-8499-7191645db5a6"/>
</RuleList>
</RuleTask>
<RuleTask ExecutionMode="Fastpath" ExitCriteria="None" Identifier="dispose of review" Ordering="Default">
<RuleList>
<Package Name="dispose of review"/>
</RuleList>
</RuleTask>
<StopTask Identifier="task_1">
<Actions Language="irl"><![CDATA[System.out.println(review.disposition);]]></Actions>
</StopTask>
</TaskList>
<NodeList>
<TaskNode Identifier="node_0" Task="task_0"/>
<TaskNode Identifier="node_1" Task="task_1"/>
<TaskNode Identifier="node_2" Task="determine review sentiment"/>
<TaskNode Identifier="node_3" Task="dispose of review"/>
<BranchNode Identifier="node_4"/>
</NodeList>
<TransitionList>
<Transition Identifier="transition_0" Source="node_0" Target="node_2"/>
<Transition Identifier="transition_1" Source="node_2" Target="node_4"/>
<Transition Identifier="transition_2" Source="node_3" Target="node_1"/>
<Transition Identifier="transition_3" Source="node_4" Target="node_3">
<Conditions Language="bal"><![CDATA[the invocation of 'the LLM service' was successful]]></Conditions>
</Transition>
<Transition Identifier="transition_4" Source="node_4" Target="node_1"/>
</TransitionList>
</Body>
<Resources>
<ResourceSet Locale="en_US">
<Data Name="node_2#height">68.103516</Data>
<Data Name="node_4#width">36.414215</Data>
<Data Name="node_1#height">19.999987</Data>
<Data Name="node_3#height">53.402344</Data>
<Data Name="node_0#height">21.0</Data>
<Data Name="node_4#height">36.414215</Data>
<Data Name="transition_3#label">LLM invocation was successful</Data>
<Data Name="node_2#name">node_2</Data>
<Data Name="node_2#width">128.70117</Data>
<Data Name="node_0#width">21.0</Data>
<Data Name="node_3#y">302.2189</Data>
<Data Name="node_4#x">64.3506</Data>
<Data Name="node_4#y">207.31062</Data>
<Data Name="node_0#x">64.350586</Data>
<Data Name="node_0#y">10.5</Data>
<Data Name="node_1#x">64.350586</Data>
<Data Name="node_1#y">388.92004</Data>
<Data Name="node_2#x">64.350586</Data>
<Data Name="node_2#y">105.05176</Data>
<Data Name="node_3#x">102.350586</Data>
<Data Name="node_1#name">node_2</Data>
<Data Name="node_3#width">102.0</Data>
<Data Name="node_4#name">node_6</Data>
<Data Name="node_1#width">20.000004</Data>
<Data Name="node_0#name">node_0</Data>
<Data Name="node_3#name">node_3</Data>
</ResourceSet>
</Resources>
<Properties/>
</Ruleflow>
</rfModel>
</ilog.rules.studio.model.ruleflow:RuleFlow>
6 changes: 6 additions & 0 deletions customer-review-rules/rules/decision parameters.var
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<ilog.rules.studio.model.base:VariableSet xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:ilog.rules.studio.model.base="http://ilog.rules.studio/model/base.ecore">
<name>decision parameters</name>
<uuid>b8312ee5-0dc4-44ab-9f26-bf2f2efbb1f3</uuid>
<variables name="review" type="com.acme.CustomerReview" initialValue="" verbalization="review"/>
</ilog.rules.studio.model.base:VariableSet>
5 changes: 5 additions & 0 deletions customer-review-rules/rules/determine sentiment/.rulepackage
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ilog.rules.studio.model.base:RulePackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:ilog.rules.studio.model.base="http://ilog.rules.studio/model/base.ecore">
<name>determine sentiment</name>
<uuid>b5414378-bc0b-4f44-9a34-b8035710548e</uuid>
</ilog.rules.studio.model.base:RulePackage>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<ilog.rules.studio.model.brl:ActionRule xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:ilog.rules.studio.model.brl="http://ilog.rules.studio/model/brl.ecore">
<name>initialize prompt</name>
<uuid>1754707d-4258-4b65-b759-0fbdf0e4d730</uuid>
<locale>en_US</locale>
<definition><![CDATA[then
set the prompt template of 'the LLM service' to 'sentiment extraction' ;
add variable ["{review}" = the content of review] to 'the LLM service' ;
]]></definition>
</ilog.rules.studio.model.brl:ActionRule>
11 changes: 11 additions & 0 deletions customer-review-rules/rules/determine sentiment/run inference.brl
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<ilog.rules.studio.model.brl:ActionRule xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:ilog.rules.studio.model.brl="http://ilog.rules.studio/model/brl.ecore">
<name>run inference</name>
<uuid>7cdfa6cd-5389-4ef1-8499-7191645db5a6</uuid>
<locale>en_US</locale>
<definition><![CDATA[then
run inference on 'the LLM service' ;
set the sentiment of review to the sentiment from the output of 'the LLM service' ;
]]></definition>
</ilog.rules.studio.model.brl:ActionRule>
5 changes: 5 additions & 0 deletions customer-review-rules/rules/dispose of review/.rulepackage
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ilog.rules.studio.model.base:RulePackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:ilog.rules.studio.model.base="http://ilog.rules.studio/model/base.ecore">
<name>dispose of review</name>
<uuid>2bdd2033-3625-4b32-aed6-186fe1e613dd</uuid>
</ilog.rules.studio.model.base:RulePackage>
Loading

0 comments on commit 74dc9b7

Please sign in to comment.