cpee-llm 1.0.6 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +15 -0
- data/cpee-llm.gemspec +1 -1
- data/lib/cpee/llm/functions.rb +76 -73
- data/lib/cpee/llm/implementation.rb +39 -13
- data/lib/cpee/llm/implementation.xml +34 -1
- data/lib/cpee/llm/prompts/system/adapt_docxml_description.txt +50 -0
- data/lib/cpee/llm/prompts/{adapt_xml_endpoints.txt → system/adapt_xml_endpoints.txt} +1 -76
- data/lib/cpee/llm/prompts/system/cpee_xml.txt +99 -0
- data/lib/cpee/llm/prompts/system/cpee_xml_documentation_modelling.txt +35 -0
- data/lib/cpee/llm/prompts/system/intent.txt +45 -0
- data/lib/cpee/llm/prompts/user/cpee_repair.txt +5 -0
- data/lib/cpee/llm/prompts/user/dataflow.txt +9 -0
- data/lib/cpee/llm/prompts/user/intent.txt +17 -0
- data/lib/cpee/llm/prompts/user/process_description.txt +5 -0
- data/lib/cpee/llm/prompts/user/process_description_endpoints.txt +9 -0
- data/lib/cpee/llm/prompts/user/process_model_adapt.txt +8 -0
- data/lib/cpee/llm/prompts/user/process_model_adapt_api.txt +11 -0
- data/lib/cpee/llm/prompts/user/process_model_text.txt +4 -0
- data/lib/cpee/llm/prompts/user/repair.txt +5 -0
- data/lib/cpee/llm/rubyllm_requests.rb +64 -116
- data/server/connect_gemini +1 -1
- data/server/connect_gpt +1 -1
- data/server/connect_morpheus +1 -1
- data/server/cpee-llm +1 -1
- data/server/plugins.json +51 -0
- data/tools/cpee-llm-tool +1 -1
- metadata +27 -14
- data/lib/cpee/llm/prompts/adapt_docxml_description.txt +0 -131
- /data/lib/cpee/llm/prompts/{apply.txt → system/apply.txt} +0 -0
- /data/lib/cpee/llm/prompts/{dataflow.txt → system/dataflow.txt} +0 -0
- /data/lib/cpee/llm/prompts/{derive.txt → system/derive.txt} +0 -0
- /data/lib/cpee/llm/prompts/{describe.txt → system/describe.txt} +0 -0
- /data/lib/cpee/llm/prompts/{gemini-request.json → system/gemini-request.json} +0 -0
- /data/lib/cpee/llm/prompts/{generate1.txt → system/generate1.txt} +0 -0
- /data/lib/cpee/llm/prompts/{generate_enpoints.txt → system/generate_enpoints.txt} +0 -0
- /data/lib/cpee/llm/prompts/{generate_enpoints1.txt → system/generate_enpoints1.txt} +0 -0
- /data/lib/cpee/llm/prompts/{identify.txt → system/identify.txt} +0 -0
- /data/lib/cpee/llm/prompts/{validate_mermaid.xml → system/validate_mermaid.xml} +0 -0
- /data/lib/cpee/llm/prompts/{validate_xml.txt → system/validate_xml.txt} +0 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# CPEE XML Process Model Structure
|
|
2
|
+
The process model itself is contained entirely inside the <description color=""> element. Interpret the XML inside <description> using the following mapping.
|
|
3
|
+
The color attribute controls the color of the whole process model. Individual service task colors can be set (see below). For the color attribute the same color palette as described in the section Service Task applies.
|
|
4
|
+
|
|
5
|
+
## Sequential Flow
|
|
6
|
+
Sequential execution is represented by sibling XML elements appearing in order inside the same parent element.
|
|
7
|
+
|
|
8
|
+
## Service Task
|
|
9
|
+
A BPMN Service Task is represented by a `<call id="..." endpoint="...">` element.
|
|
10
|
+
The endpoint of the service is stored in the **endpoint attribute**.
|
|
11
|
+
<call endpoint="measurelightingconditions">
|
|
12
|
+
The following child elements may appear inside `<call>`:
|
|
13
|
+
├── parameters
|
|
14
|
+
│ ├── label
|
|
15
|
+
│ ├── color
|
|
16
|
+
│ ├── method
|
|
17
|
+
│ └── arguments
|
|
18
|
+
├── code
|
|
19
|
+
│ ├── signal
|
|
20
|
+
│ ├── prepare
|
|
21
|
+
│ ├── finalize
|
|
22
|
+
│ ├── update
|
|
23
|
+
│ └── rescue
|
|
24
|
+
├── annotations
|
|
25
|
+
└── documentation
|
|
26
|
+
|
|
27
|
+
The parameters element stores task metadata, such as its label and display color. The <label> is the task name. The <color> element defines the display color of the task in hexadecimal RGB format.
|
|
28
|
+
Use only the following color palette:
|
|
29
|
+
* White — #ffffff
|
|
30
|
+
* Blue — #d4e1f1
|
|
31
|
+
* Green — #d8f0dd
|
|
32
|
+
* Yellow — #ffffcc
|
|
33
|
+
* Purple — #e4c3e4
|
|
34
|
+
* Pink — #f8a8c6
|
|
35
|
+
* Brown — #ded0c5
|
|
36
|
+
* Gray — #deddda
|
|
37
|
+
|
|
38
|
+
The <method> field must strictly follow the Service Registry specification.
|
|
39
|
+
If the service specification defines a method, use exactly that value. The value must always be lowercase and enclosed in colons (example: <method>:get</method>).
|
|
40
|
+
Never invent, infer, or assume a method value that is not explicitly defined in the service specification:
|
|
41
|
+
<method/>
|
|
42
|
+
|
|
43
|
+
Service input parameters are stored inside arguments. Each argument is represented by its own child element.
|
|
44
|
+
<arguments>
|
|
45
|
+
<min>1</min>
|
|
46
|
+
<max>100</max>
|
|
47
|
+
</arguments>
|
|
48
|
+
If an argument depends on a previously computed or returned value, it must be provided using the !data.some_value syntax.
|
|
49
|
+
<arguments>
|
|
50
|
+
<step>!data.current_step</step>
|
|
51
|
+
</arguments>
|
|
52
|
+
|
|
53
|
+
Returned service values are processed inside finalize: <finalize output="result">, where result is the variable containing the service response. Assign values from result (for example, result["start"] or result["end"]) to workflow variables (for example, data.start or data.end) to store them for later use in the process.
|
|
54
|
+
<finalize output="result"> data.temperature = result["temperature"].to_f; data.type = result["celsius"];</finalize>
|
|
55
|
+
|
|
56
|
+
## Script TaskA BPMN Script Task is represented by <manipulate id="..." label="..." color="...">. The executable Ruby code is stored inside the <code> child element:
|
|
57
|
+
<manipulate><code id="a1">data.counter += 1</code></manipulate>
|
|
58
|
+
The label of the BPMN Script Task is stored in an attribute label in the <manipulate>.
|
|
59
|
+
The color of the BPMN Script Task is stored in an attribute color in the <manipulate>. Use the same color palette as for Service Tasks.
|
|
60
|
+
|
|
61
|
+
## Exclusive Gateway
|
|
62
|
+
An Exclusive Gateway is represented by <choose eid="..." mode="exclusive">
|
|
63
|
+
Each outgoing branch is represented by <alternative condition="..." eid="e.."> child.
|
|
64
|
+
The branch condition is stored in the **condition attribute**.
|
|
65
|
+
<alternative condition="data.temperature > 30" eid="e1">
|
|
66
|
+
Conditions must be valid Ruby expressions.
|
|
67
|
+
Default branch has no conditions. <otherwise eid="..."/>.
|
|
68
|
+
|
|
69
|
+
## Inclusive Gateway
|
|
70
|
+
The only differ from Inclusive Gateway by the attribute mode="inclusive".
|
|
71
|
+
|
|
72
|
+
## Loop
|
|
73
|
+
A BPMN loop is represented by <loop eid="e.." mode="..." condition="...">
|
|
74
|
+
The loop condition is stored in the **condition attribute**. The loop execution mode is stored in the **mode attribute**.
|
|
75
|
+
pre_test is used for head controlled loops.
|
|
76
|
+
post_test is used for tail controlled loops.
|
|
77
|
+
<loop eid="e1" mode="pre_test" condition="data.counter < 10">
|
|
78
|
+
Loop conditions must be valid Ruby expressions.
|
|
79
|
+
|
|
80
|
+
## Parallel Gateway
|
|
81
|
+
Parallel execution is represented by <parallel eid="e.." wait="-1" cancel="last">
|
|
82
|
+
The attribute wait defines how many branches have to reach the cancel condition before other branches are considered invalid. A normal parallel has always wait="-1".
|
|
83
|
+
The attribute cancel defines the cancel condition, i.e., if the wait rules are evaluated after a branch fully finishes (attribute cancel has the value "last"), or if the wait rules are evaluated after the first task of a branch finishes ((attribute cancel has the value "first").
|
|
84
|
+
An event-based gateway (which is a special case of a parallel) has always wait="1" cancel="last".
|
|
85
|
+
Each concurrent branch is represented by <parallel_branch eid="e..">
|
|
86
|
+
|
|
87
|
+
##Pause Task
|
|
88
|
+
A pause is represented by a <stop id="a.."> element.
|
|
89
|
+
A <stop> pauses the execution of the process (until it is manually resumed). It does not terminate the process.
|
|
90
|
+
<stop id="a5"/>
|
|
91
|
+
When the user requests to pause, hold, or stop the process, insert a <stop> element.
|
|
92
|
+
The id attribute must be unique within the process model. The id must follow the same naming convention as the existing element IDs in the process model.
|
|
93
|
+
Insert the <stop> element at the location specified or implied by the user's request. Otherwise, insert the <stop> element as the last element of the process.
|
|
94
|
+
|
|
95
|
+
## Variables
|
|
96
|
+
Variables are referenced as: data.variable_name
|
|
97
|
+
Service outputs are returned as strings unless otherwise specified.
|
|
98
|
+
Whenever a value represents a numeric type (integer or floating-point), convert it to a numeric value before assigning it to a workflow variable by using Ruby's .to_f method:
|
|
99
|
+
data.temperature = result["temperature"].to_f
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
## Documentation
|
|
2
|
+
|
|
3
|
+
The child documentation may appear inside `<call>` (on the same level as parameters), and can have the following structure:
|
|
4
|
+
├── ...
|
|
5
|
+
└── documentation
|
|
6
|
+
├── implementation
|
|
7
|
+
│ └── description
|
|
8
|
+
├── in
|
|
9
|
+
│ └── description
|
|
10
|
+
└── out
|
|
11
|
+
└── description
|
|
12
|
+
|
|
13
|
+
The documentation element may describe the service implementation as well as its expected inputs and produced outputs.
|
|
14
|
+
The <description> elements contain optional textual information about the task's behavior, including the process variables consumed (<in>), produced (<out>), or implementation-specific details (<implementation>).
|
|
15
|
+
Empty <description> elements indicate that no additional semantic information is provided.
|
|
16
|
+
|
|
17
|
+
If a `<documentation>` element does not exist for a Service Task, append an empty `<documentation>` element. Empty `<documentation>` conmtains only <in> and <implementation>. Include <out> only in tasks, where output is defined.
|
|
18
|
+
|
|
19
|
+
#Outputs:
|
|
20
|
+
Every new output created by the Service Task must be added to the <out><description> element.
|
|
21
|
+
Output variables must use the workflow variable format:
|
|
22
|
+
data.variable_name = "name of document or document content"
|
|
23
|
+
If the output represents a document, specify whether the variable stores the document name or the document content.
|
|
24
|
+
data.invoice_name = "invoice.pdf" or data.invoice_content = "content of the invoice document"
|
|
25
|
+
Each newly created output must introduce a new data. variable.
|
|
26
|
+
|
|
27
|
+
#Inputs:
|
|
28
|
+
Inputs describe the workflow variables consumed by the Service Task.
|
|
29
|
+
An input can either:
|
|
30
|
+
Use an existing output variable from a previous Service Task, or Introduce a new workflow variable.
|
|
31
|
+
If the input is based on an existing output, use the same data. variable name defined in the output:
|
|
32
|
+
data.invoice_content
|
|
33
|
+
If the input is new and has no previous output source, define a new variable:
|
|
34
|
+
data.customer_information = "content of the invoice"
|
|
35
|
+
Do not create a new variable name when an existing output already contains the required data. Reuse the existing data. variable.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
Normally the input of a user is used to create or edit a process model.
|
|
2
|
+
Typically this entails adding, deleting or moving tasks, setting parameters for
|
|
3
|
+
tasks, or creating a model for a certain domain or topic.
|
|
4
|
+
|
|
5
|
+
Additionally the input, or parts of the input can be passed to a plugin.
|
|
6
|
+
Plugins are defined as json, e.g.:
|
|
7
|
+
|
|
8
|
+
{ "id": 1, "priority": 2, "url": "https://cpee.org/llm/plugins/aaa", "description": "Description what the plugin does", ... }
|
|
9
|
+
|
|
10
|
+
If one of the plugins is matchin (according to its description), return its id
|
|
11
|
+
as json { 'id': 12345}. \ If multiple plugins match, choose the one with the
|
|
12
|
+
lowest priority. If one the plugins is only partially suitable, remove that
|
|
13
|
+
part of the text that the plugin requires as input, and replace it with %%%.
|
|
14
|
+
Write the text into a key "input". Replacing the whole input with %%% is fine.
|
|
15
|
+
Replacing a part is also fine, depending on the user input.
|
|
16
|
+
|
|
17
|
+
For example with the plugin:
|
|
18
|
+
|
|
19
|
+
{ "id": 1, "url": "https://cpee.org/llm/plugins/aaa", "description": "Extracts a color value from a color name." }
|
|
20
|
+
|
|
21
|
+
And the user input:
|
|
22
|
+
|
|
23
|
+
"Change the process model to occarina blue."
|
|
24
|
+
|
|
25
|
+
Return the following:
|
|
26
|
+
|
|
27
|
+
{ "id": 1, "input": "Change the process model to %%%." }
|
|
28
|
+
|
|
29
|
+
If the description tells that it returns multiple names values, and enumerates
|
|
30
|
+
them, output should look like this:
|
|
31
|
+
|
|
32
|
+
{ "id": 12345, "input": "create a process model with %%%tasks %%%endpoints" }
|
|
33
|
+
|
|
34
|
+
A plugin's description may refer to a general category of thing (a document, a
|
|
35
|
+
color, a value, ...) rather than one specific named instance. A vague or
|
|
36
|
+
generic reference to that category in the user input (e.g. "the document",
|
|
37
|
+
"that file", "some color") still counts as a match for the plugin - the user
|
|
38
|
+
does not have to name the specific instance.
|
|
39
|
+
|
|
40
|
+
If the input contains several clauses, evaluate each clause against every
|
|
41
|
+
plugin's description separately, don't just judge the input as a whole. One
|
|
42
|
+
clause can match a plugin while the rest of the input is unrelated process
|
|
43
|
+
model editing; use the %%% substitution rule above for that clause and leave
|
|
44
|
+
the rest of the text as is. Only return "{}" once no plugin's description
|
|
45
|
+
matches any clause in the input.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Consider the following user input:
|
|
2
|
+
|
|
3
|
+
%%%user_input
|
|
4
|
+
|
|
5
|
+
Consider the follwing list of plugins
|
|
6
|
+
|
|
7
|
+
%%%plugins
|
|
8
|
+
|
|
9
|
+
If appropriate, select a plugin, and return its id as json, e.g., { 'id': 123 }.
|
|
10
|
+
If a plugin is appropriate for a part of the text, replace the text with %%% and return it as part of the json, e.g., { "id": 123, "text": "Some text. %%%. Some more text." }.
|
|
11
|
+
If nothing seems suitable return "null". This includes cases where the user input
|
|
12
|
+
does not convey any intent about creating, adding to, or modifying a process
|
|
13
|
+
model at all, e.g. "what is the weather today", "2+2", or "12".
|
|
14
|
+
If it seems like the text is just for creating or modifying a process model
|
|
15
|
+
return "{}". This includes creating, updating, or modifying a task, event, or
|
|
16
|
+
gateway, changing the documentation of a task, or adding or changing
|
|
17
|
+
information in any field of a task, e.g. "make task a2 pink".
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
Consider the following process description:
|
|
2
|
+
|
|
3
|
+
%%%user_input
|
|
4
|
+
|
|
5
|
+
... and consider the the provided endpoint list:
|
|
6
|
+
|
|
7
|
+
%%%endpoints
|
|
8
|
+
|
|
9
|
+
Interpret the process description as business intent and generate an executable BPMN model in Mermaid.js format using only the available endpoint capabilities.
|
|
@@ -17,13 +17,15 @@
|
|
|
17
17
|
require 'ruby_llm'
|
|
18
18
|
require 'typhoeus'
|
|
19
19
|
require 'json'
|
|
20
|
+
require 'mime/types'
|
|
21
|
+
require 'securerandom'
|
|
20
22
|
|
|
21
23
|
module CPEE
|
|
22
24
|
|
|
23
25
|
module LLM
|
|
24
26
|
|
|
25
|
-
#
|
|
26
|
-
class LLMError < StandardError
|
|
27
|
+
# custom llm error class #{{{
|
|
28
|
+
class LLMError < StandardError
|
|
27
29
|
attr_reader :http_response
|
|
28
30
|
def initialize(message = "Something went wrong", http_response = 500)
|
|
29
31
|
@http_response = http_response
|
|
@@ -35,141 +37,87 @@ module CPEE
|
|
|
35
37
|
|
|
36
38
|
def connect_llm(myllm,llms) #{{{
|
|
37
39
|
chat = nil
|
|
38
|
-
RubyLLM.
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
context = RubyLLM.context
|
|
41
|
+
config = context.config
|
|
42
|
+
config.request_timeout = llms[:request_timeout]
|
|
43
|
+
config.max_retries = llms[:max_retries]
|
|
44
|
+
|
|
45
|
+
llms[:connectors].each do |k,v|
|
|
46
|
+
if myllm =~ /#{k}/ && chat.nil?
|
|
47
|
+
chat = eval(v)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
if chat.nil?
|
|
52
|
+
raise LLMError.new("Selected LLM model does not exist or is not supported. Please, select another LLM model.", 400)
|
|
53
|
+
end
|
|
54
|
+
return chat
|
|
55
|
+
end #}}}
|
|
41
56
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
57
|
+
def build_system_prompt(name) #{{{
|
|
58
|
+
sp = File.read(File.join(__dir__,"prompts","system",name))
|
|
59
|
+
sp.gsub!(/(^|\n)[\t ]*%%%([^\n]+)(\n|$)/) do |e|
|
|
60
|
+
b = $1
|
|
61
|
+
m = $2
|
|
62
|
+
a = $3
|
|
63
|
+
if File.exist? File.join(__dir__,"prompts","system",m)
|
|
64
|
+
"#{a}#{File.read(File.join(__dir__,"prompts","system",m))}#{b}"
|
|
65
|
+
else
|
|
66
|
+
"#{a}#{b}"
|
|
46
67
|
end
|
|
68
|
+
end
|
|
69
|
+
sp
|
|
70
|
+
end #}}}
|
|
47
71
|
|
|
48
|
-
|
|
49
|
-
|
|
72
|
+
def build_user_prompt(name,opts) #{{{
|
|
73
|
+
sp = File.read(File.join(__dir__,"prompts","user",name))
|
|
74
|
+
sp.gsub!(/(^|\n)[\t ]*%%%([^\n]+)(\n|$)/) do |e|
|
|
75
|
+
b = $1
|
|
76
|
+
m = $2.to_sym
|
|
77
|
+
a = $3
|
|
78
|
+
if opts[m]
|
|
79
|
+
"#{a}#{opts[m]}#{b}"
|
|
80
|
+
else
|
|
81
|
+
"#{a}#{b}"
|
|
50
82
|
end
|
|
51
83
|
end
|
|
52
|
-
|
|
84
|
+
sp
|
|
53
85
|
end #}}}
|
|
54
86
|
|
|
55
|
-
def generate_content(myllm, system_prompt, user_prompt, max_tokens, temperature, llms) #{{{
|
|
87
|
+
def generate_content(myllm, system_prompt, user_prompt, max_tokens, temperature, llms, opts={}, documents=[]) #{{{
|
|
88
|
+
temperature = temperature.nil? ? 0.1 : temperature.to_f
|
|
56
89
|
chat = connect_llm(myllm,llms)
|
|
57
90
|
chat.with_instructions system_prompt
|
|
58
91
|
chat.with_temperature(temperature)
|
|
59
92
|
if max_tokens != 0
|
|
60
93
|
if myllm.include?("gemini")
|
|
61
|
-
|
|
94
|
+
opts[:generationConfig] = { maxOutputTokens: max_tokens }
|
|
95
|
+
opts[:generationConfig].merge!(response_mime_type: 'application/json') if opts[:json]
|
|
62
96
|
elsif myllm.include?("gpt")
|
|
63
|
-
|
|
97
|
+
opts[:max_completion_tokens] = max_tokens
|
|
98
|
+
opts[:response_format] = { type: "json_object" } if opts[:json]
|
|
64
99
|
else
|
|
65
|
-
|
|
100
|
+
opts[:max_tokens] = max_tokens
|
|
66
101
|
end
|
|
67
102
|
end
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
chat.
|
|
81
|
-
chat.with_instructions system_prompt
|
|
82
|
-
chat.with_temperature(temperature)
|
|
83
|
-
response = chat.ask user_prompt
|
|
84
|
-
#puts JSON.parse(response.content)
|
|
103
|
+
opts.delete(:json)
|
|
104
|
+
chat.with_params **opts
|
|
105
|
+
message = RubyLLM::Content.new(user_prompt)
|
|
106
|
+
documents.each do |doc|
|
|
107
|
+
filename = doc.filename
|
|
108
|
+
if (filename.nil? || filename.empty?) && !doc.mimetype.to_s.empty?
|
|
109
|
+
extension = MIME::Types[doc.mimetype].first&.extensions&.first
|
|
110
|
+
filename = SecureRandom.hex(8)
|
|
111
|
+
filename += ".#{extension}" if extension
|
|
112
|
+
end
|
|
113
|
+
message.add_attachment(doc.value, filename:)
|
|
114
|
+
end
|
|
115
|
+
response = chat.ask message
|
|
85
116
|
return response.content
|
|
86
117
|
rescue Faraday::TimeoutError => e
|
|
87
118
|
raise LLMError.new(e.message, 504)
|
|
88
119
|
rescue Exception => e
|
|
89
120
|
raise LLMError.new(e.message, 500)
|
|
90
|
-
end #}}}
|
|
91
|
-
|
|
92
|
-
def generate_mermaid_model(llm, user_input, temperature, llms={}) #{{{
|
|
93
|
-
max_tokens = 4000
|
|
94
|
-
temperature = temperature.nil? ? 0.1 : temperature.to_f
|
|
95
|
-
system_prompt = File.read(File.join(__dir__,"prompts/generate1.txt"))
|
|
96
|
-
user_prompt = "Consider following process description: #{user_input}. Generate a BPMN model in Mermaid.js format."
|
|
97
|
-
new_mermaid = generate_content(llm,system_prompt,user_prompt,max_tokens,temperature,llms)
|
|
98
|
-
return new_mermaid
|
|
99
|
-
end #}}}
|
|
100
|
-
|
|
101
|
-
def adapt_mermaid_model(llm, user_input, process_model, llms={}) #{{{
|
|
102
|
-
max_tokens = 4000
|
|
103
|
-
temperature = 0
|
|
104
|
-
system_prompt = File.read(File.join(__dir__,"prompts/apply.txt"))
|
|
105
|
-
user_prompt = "Consider following process model: #{process_model}. Update this process model according to provided changes #{user_input}."
|
|
106
|
-
new_mermaid = generate_content(llm,system_prompt,user_prompt,max_tokens,temperature,llms)
|
|
107
|
-
return new_mermaid
|
|
108
|
-
end #}}}
|
|
109
|
-
|
|
110
|
-
def adapt_docxml_description(llm, user_input, process_model, llms={}) #{{{
|
|
111
|
-
max_tokens = 20000
|
|
112
|
-
temperature = 0
|
|
113
|
-
system_prompt = File.read(File.join(__dir__,"prompts/adapt_docxml_description.txt"))
|
|
114
|
-
user_prompt = "Consider following process model: #{process_model}. Update this process model according to provided changes #{user_input}."
|
|
115
|
-
new_cpee = generate_content(llm,system_prompt,user_prompt,max_tokens,temperature,llms)
|
|
116
|
-
return new_cpee
|
|
117
|
-
end #}}}
|
|
118
|
-
|
|
119
|
-
def adapt_xml_model(llm, user_input, process_model, api_specification, llms={}) #{{{
|
|
120
|
-
max_tokens = 20000
|
|
121
|
-
temperature = 0
|
|
122
|
-
system_prompt = File.read(File.join(__dir__,"prompts/adapt_xml_endpoints.txt"))
|
|
123
|
-
user_prompt = "Consider following process model: #{process_model.to_s} and task specification #{api_specification} with endpoint data. Update this process model according to provided changes #{user_input}."
|
|
124
|
-
new_cpee = generate_content(llm,system_prompt,user_prompt,max_tokens,temperature,llms)
|
|
125
|
-
return new_cpee
|
|
126
|
-
end #}}}
|
|
127
|
-
|
|
128
|
-
def generate_plain_text(llm, user_input, llms={}) #{{{
|
|
129
|
-
max_tokens = 4000
|
|
130
|
-
temperature = 0
|
|
131
|
-
system_prompt = File.read(File.join(__dir__,"prompts/describe.txt"))
|
|
132
|
-
user_prompt = "Consider following process process model: #{user_input}. Generate a text describing provided process description."
|
|
133
|
-
process_description = generate_content(llm,system_prompt,user_prompt,max_tokens,temperature,llms)
|
|
134
|
-
return process_description
|
|
135
|
-
end #}}}
|
|
136
|
-
|
|
137
|
-
def generate_generic_content(llm, user_input, system_prompt, json, temperature, llms={}) #{{{
|
|
138
|
-
max_tokens = 20000
|
|
139
|
-
temperature = temperature.nil? ? 0 : temperature.to_f
|
|
140
|
-
if json == 'true'
|
|
141
|
-
process_description = generate_json_content(llm,system_prompt,user_input,max_tokens,temperature,llms)
|
|
142
|
-
else
|
|
143
|
-
process_description = generate_content(llm,system_prompt,user_input,max_tokens,temperature,llms)
|
|
144
|
-
end
|
|
145
|
-
return process_description
|
|
146
|
-
end #}}}
|
|
147
|
-
|
|
148
|
-
def generate_dataflow_content(llm, mermaid_model, api_specification, llms={}) #{{{
|
|
149
|
-
max_tokens = 10000
|
|
150
|
-
temperature = 0.1
|
|
151
|
-
system_prompt = File.read(File.join(__dir__,"prompts/dataflow.txt"))
|
|
152
|
-
user_prompt = "Given process mode #{mermaid_model} and task specification #{api_specification} with endpoint data, define the execution context and return a JSON specification."
|
|
153
|
-
dataflow = generate_content(llm,system_prompt,user_prompt,max_tokens,temperature,llms)
|
|
154
|
-
return dataflow
|
|
155
|
-
end #}}}
|
|
156
|
-
|
|
157
|
-
def generate_endpoint_mermaid_model(llm, user_input, endpoints, llms={}) #{{{
|
|
158
|
-
max_tokens = 4000
|
|
159
|
-
temperature = 0.1
|
|
160
|
-
system_prompt = File.read(File.join(__dir__,"prompts/generate_enpoints.txt"))
|
|
161
|
-
user_prompt = "Consider the following process description: #{user_input} and the provided endpoint list: #{endpoints}. Interpret the process description as business intent and generate an executable BPMN model in Mermaid.js format using only the available endpoint capabilities."
|
|
162
|
-
new_mermaid = generate_content(llm,system_prompt,user_prompt,max_tokens,temperature,llms)
|
|
163
|
-
return new_mermaid
|
|
164
|
-
end #}}}
|
|
165
|
-
|
|
166
|
-
def validate_xml_model(llm, cpee_model, llms={}) #{{{
|
|
167
|
-
max_tokens = 0
|
|
168
|
-
temperature = 0.1
|
|
169
|
-
system_prompt = File.read(File.join(__dir__,"prompts/validate_xml.txt"))
|
|
170
|
-
user_prompt = "Consider following CPEE XML promcess model created by autobpmn.ai: #{cpee_model}. Repair the model so that it becomes executable. Return only the repaired XML without any comments or markdown formatting."
|
|
171
|
-
repaired_cpee = generate_content(llm,system_prompt,user_prompt,max_tokens,temperature,llms)
|
|
172
|
-
return repaired_cpee
|
|
173
121
|
end #}}}
|
|
174
122
|
|
|
175
123
|
end
|
data/server/connect_gemini
CHANGED
data/server/connect_gpt
CHANGED
data/server/connect_morpheus
CHANGED
|
@@ -2,4 +2,4 @@ config.openai_api_key = 'insert your key here'
|
|
|
2
2
|
config.openai_api_base = "https://morpheus.cit.tum.de/api/v1"
|
|
3
3
|
config.openai_use_system_role = true
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
context.chat(model: myllm,provider: :openai,assume_model_exists: true)
|
data/server/cpee-llm
CHANGED
data/server/plugins.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"id": 1,
|
|
4
|
+
"priority": 1,
|
|
5
|
+
"url": "https://echo.bpm.in.tum.de/services/llm/dnames/",
|
|
6
|
+
"description": "Use ONLY when the user wants to know whether a document exists or where it is, and plans no further operation on it (e.g. 'does the spec document exist', 'where is the process document'). A vague or generic reference (e.g. 'the process document', 'that file') still counts as a document reference, it does not need to be a specific file name. Looks up the document, extracts its url, and outputs the result directly to chat. If the input hints at any further operation on the document (analyse, extract, look at, summarize, use it to build or modify a process model, ...), do NOT use this plugin - use plugin id 2 instead.",
|
|
7
|
+
"required_input": [
|
|
8
|
+
"documents"
|
|
9
|
+
],
|
|
10
|
+
"output": "chat"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"id": 2,
|
|
14
|
+
"priority": 1,
|
|
15
|
+
"url": "https://echo.bpm.in.tum.de/services/llm/dnames/",
|
|
16
|
+
"description": "Use when the user wants to look up a document AND then do something further with it (analyse it, extract from it, use it to create or modify a process model, ...), e.g. 'analyse the process document and create a process from it'. A vague or generic reference (e.g. 'the process document', 'that file') still counts as a document reference, it does not need to be a specific file name. Looks up the document, extracts its url, and inserts the result back into the text so a subsequent plugin selection pass can pick up from there. If the input hints at NO further operation on the document, do NOT use this plugin - use plugin id 1 instead.",
|
|
17
|
+
"required_input": [
|
|
18
|
+
"documents"
|
|
19
|
+
],
|
|
20
|
+
"output": "reintent"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"id": 3,
|
|
24
|
+
"priority": 2,
|
|
25
|
+
"url": "https://echo.bpm.in.tum.de/services/llm/documents/",
|
|
26
|
+
"description": "Use ONLY when a document url is already given in the input (not a symbolic/vague document name - if only a name is given, use plugin id 2 to resolve it to a url first) AND the user just wants the document's content described or extracted, with no explicit intention to use the result to build or change the process model. Analyses, extracts from, or otherwise works on the document at the given url and outputs the textual result to chat. If the input explicitly signifies that the result should feed into creating or modifying the process model (e.g. 'and create a process from it', 'and modify the model with the result', 'add it to the model'), do NOT use this plugin - use plugin id 4 instead.",
|
|
27
|
+
"required_input": [],
|
|
28
|
+
"output_template": "%%%",
|
|
29
|
+
"output": "chat"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"id": 4,
|
|
33
|
+
"priority": 2,
|
|
34
|
+
"url": "https://echo.bpm.in.tum.de/services/llm/documents/",
|
|
35
|
+
"description": "Use when a document url is already given in the input (not a symbolic/vague document name - if only a name is given, use plugin id 2 to resolve it to a url first) AND the input explicitly signifies that the result should feed into creating or modifying the process model, e.g. 'and create a process from it', 'and build a model from it', 'and modify the models with the result', or 'add it to the model'. Analyses, extracts from, or otherwise works on the document at the given url and feeds the textual result back into the pipeline so it is used to create or modify the process model. If the input has no such explicit intention to affect the model, do NOT use this plugin - use plugin id 3 instead.",
|
|
36
|
+
"required_input": [],
|
|
37
|
+
"output_template": "%%%",
|
|
38
|
+
"output": "pipe"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"id": 5,
|
|
42
|
+
"priority": 2,
|
|
43
|
+
"url": "https://echo.bpm.in.tum.de/services/llm/stats/",
|
|
44
|
+
"description": "Answer a questions about the process model. This should relate to tasks, gateways or events, or any information contained in them. It can also relate to quantitative properties of the process, e.g. 'how many tasks'.",
|
|
45
|
+
"required_input": [
|
|
46
|
+
"model"
|
|
47
|
+
],
|
|
48
|
+
"output_template": "%%%",
|
|
49
|
+
"output": "chat"
|
|
50
|
+
}
|
|
51
|
+
]
|
data/tools/cpee-llm-tool
CHANGED
|
@@ -27,7 +27,7 @@ require 'typhoeus'
|
|
|
27
27
|
# ./cpee-llm-tool.rb adapt 'Add task A after dismissal review.' 'geminin-2.0-flash' 1501
|
|
28
28
|
|
|
29
29
|
|
|
30
|
-
srv = Riddl::Client.new('http://localhost:
|
|
30
|
+
srv = Riddl::Client.new('http://localhost:9305/')
|
|
31
31
|
status, res = srv.post [
|
|
32
32
|
Riddl::Parameter::Complex.new("rpst_xml","text/xml",ARGV[0] == 'adapt' ? Typhoeus.get("https://cpee.org/flow/engine/#{ARGV[2]}/properties/dslx/").response_body() : File.read('cpee_empty_example')),
|
|
33
33
|
Riddl::Parameter::Complex.new("user_input","text/plain",ARGV[1]),
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: cpee-llm
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0
|
|
4
|
+
version: 1.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Nataliia Klievtsova
|
|
@@ -126,25 +126,38 @@ files:
|
|
|
126
126
|
- lib/cpee/llm/functions.rb
|
|
127
127
|
- lib/cpee/llm/implementation.rb
|
|
128
128
|
- lib/cpee/llm/implementation.xml
|
|
129
|
-
- lib/cpee/llm/prompts/adapt_docxml_description.txt
|
|
130
|
-
- lib/cpee/llm/prompts/adapt_xml_endpoints.txt
|
|
131
|
-
- lib/cpee/llm/prompts/apply.txt
|
|
132
|
-
- lib/cpee/llm/prompts/
|
|
133
|
-
- lib/cpee/llm/prompts/
|
|
134
|
-
- lib/cpee/llm/prompts/
|
|
135
|
-
- lib/cpee/llm/prompts/
|
|
136
|
-
- lib/cpee/llm/prompts/
|
|
137
|
-
- lib/cpee/llm/prompts/
|
|
138
|
-
- lib/cpee/llm/prompts/
|
|
139
|
-
- lib/cpee/llm/prompts/
|
|
140
|
-
- lib/cpee/llm/prompts/
|
|
141
|
-
- lib/cpee/llm/prompts/
|
|
129
|
+
- lib/cpee/llm/prompts/system/adapt_docxml_description.txt
|
|
130
|
+
- lib/cpee/llm/prompts/system/adapt_xml_endpoints.txt
|
|
131
|
+
- lib/cpee/llm/prompts/system/apply.txt
|
|
132
|
+
- lib/cpee/llm/prompts/system/cpee_xml.txt
|
|
133
|
+
- lib/cpee/llm/prompts/system/cpee_xml_documentation_modelling.txt
|
|
134
|
+
- lib/cpee/llm/prompts/system/dataflow.txt
|
|
135
|
+
- lib/cpee/llm/prompts/system/derive.txt
|
|
136
|
+
- lib/cpee/llm/prompts/system/describe.txt
|
|
137
|
+
- lib/cpee/llm/prompts/system/gemini-request.json
|
|
138
|
+
- lib/cpee/llm/prompts/system/generate1.txt
|
|
139
|
+
- lib/cpee/llm/prompts/system/generate_enpoints.txt
|
|
140
|
+
- lib/cpee/llm/prompts/system/generate_enpoints1.txt
|
|
141
|
+
- lib/cpee/llm/prompts/system/identify.txt
|
|
142
|
+
- lib/cpee/llm/prompts/system/intent.txt
|
|
143
|
+
- lib/cpee/llm/prompts/system/validate_mermaid.xml
|
|
144
|
+
- lib/cpee/llm/prompts/system/validate_xml.txt
|
|
145
|
+
- lib/cpee/llm/prompts/user/cpee_repair.txt
|
|
146
|
+
- lib/cpee/llm/prompts/user/dataflow.txt
|
|
147
|
+
- lib/cpee/llm/prompts/user/intent.txt
|
|
148
|
+
- lib/cpee/llm/prompts/user/process_description.txt
|
|
149
|
+
- lib/cpee/llm/prompts/user/process_description_endpoints.txt
|
|
150
|
+
- lib/cpee/llm/prompts/user/process_model_adapt.txt
|
|
151
|
+
- lib/cpee/llm/prompts/user/process_model_adapt_api.txt
|
|
152
|
+
- lib/cpee/llm/prompts/user/process_model_text.txt
|
|
153
|
+
- lib/cpee/llm/prompts/user/repair.txt
|
|
142
154
|
- lib/cpee/llm/rubyllm_requests.rb
|
|
143
155
|
- server/connect_gemini
|
|
144
156
|
- server/connect_gpt
|
|
145
157
|
- server/connect_morpheus
|
|
146
158
|
- server/cpee-llm
|
|
147
159
|
- server/cpee-llm.conf
|
|
160
|
+
- server/plugins.json
|
|
148
161
|
- tools/cpee-llm
|
|
149
162
|
- tools/cpee-llm-tool
|
|
150
163
|
homepage: http://github.com/etm/cpee-llm/
|