cpee-llm 1.0.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 +7 -0
- data/AUTHORS +3 -0
- data/LICENSE +165 -0
- data/README.md +7 -0
- data/Rakefile +21 -0
- data/cpee-llm.gemspec +29 -0
- data/lib/cpee/llm/dataflow.rb +199 -0
- data/lib/cpee/llm/functions.rb +248 -0
- data/lib/cpee/llm/implementation.rb +237 -0
- data/lib/cpee/llm/implementation.xml +90 -0
- data/lib/cpee/llm/prompts/adapt_xml.txt +157 -0
- data/lib/cpee/llm/prompts/apply.txt +32 -0
- data/lib/cpee/llm/prompts/dataflow.txt +171 -0
- data/lib/cpee/llm/prompts/derive.txt +28 -0
- data/lib/cpee/llm/prompts/describe.txt +5 -0
- data/lib/cpee/llm/prompts/gemini-request.json +18 -0
- data/lib/cpee/llm/prompts/generate1.txt +90 -0
- data/lib/cpee/llm/prompts/generate_enpoints.txt +132 -0
- data/lib/cpee/llm/prompts/generate_enpoints1.txt +155 -0
- data/lib/cpee/llm/prompts/identify.txt +25 -0
- data/lib/cpee/llm/prompts/validate_mermaid.xml +74 -0
- data/lib/cpee/llm/prompts/validate_xml.txt +35 -0
- data/lib/cpee/llm/rubyllm_requests.rb +172 -0
- data/server/connect_gemini +3 -0
- data/server/connect_gpt +4 -0
- data/server/connect_morpheus +5 -0
- data/server/cpee-llm +43 -0
- data/server/cpee-llm.conf +11 -0
- data/tools/cpee-llm +74 -0
- data/tools/cpee-llm-tool +49 -0
- metadata +156 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
Given the relevant the Mermaid.js BPMN model, and the provided Mermaid.js BPMN syntax and structural rules, perform the validation.
|
|
2
|
+
mermaid model: .
|
|
3
|
+
|
|
4
|
+
Mermaid.js BPMN Syntax:
|
|
5
|
+
- The graph must use the LR (Left to Right) direction.
|
|
6
|
+
- Each Mermaid.js node must have the following structure:
|
|
7
|
+
id:type:shape and label
|
|
8
|
+
- id: a unique integer from 0 to n.
|
|
9
|
+
- type: BPMN element type → startevent, endevent, task, subprocess, exclusivegateway, inclusivegateway, parallelgateway.
|
|
10
|
+
- Shapes and labels:
|
|
11
|
+
- Start event → id:startevent:((startevent))
|
|
12
|
+
- End event → id:endevent:(((endevent)))
|
|
13
|
+
- Task → id:task:(Task Label)
|
|
14
|
+
- Subprocess → id:subprocess:(Subprocess Label)
|
|
15
|
+
- Exclusive gateway → id:exclusivegateway:{x}
|
|
16
|
+
- Parallel gateway → id:parallelgateway:{AND}
|
|
17
|
+
- Inclusive gateway → id:inclusivegateway:{O}
|
|
18
|
+
|
|
19
|
+
Hard Structural Rules:
|
|
20
|
+
- Tasks:
|
|
21
|
+
- No empty tasks are allowed: every task node must have a descriptive label.
|
|
22
|
+
- “Default branches” between gateways are allowed — edges that go directly from one gateway to another without any task in between.
|
|
23
|
+
- Gateways:
|
|
24
|
+
- Every split gateway must be matched with a corresponding merge gateway of the same type.
|
|
25
|
+
- No implicit merges are allowed — merges must always be explicit.
|
|
26
|
+
- No split gateway is permitted without a matching merge.
|
|
27
|
+
- Flow correctness:
|
|
28
|
+
- Each path/branch must start from the start event and lead to the end event.
|
|
29
|
+
- Each incoming node must have its own separate edge to the target node.
|
|
30
|
+
- Reused nodes:
|
|
31
|
+
- If a node occurs more than once, reference it by repeating the full node declaration like this - id:type:shape and label (e.g., 2:task:(do something)).
|
|
32
|
+
- It is strictly prohibited to use only the ID (e.g., 2) without type and to use other short versions like id:type (e.g.,2:task).
|
|
33
|
+
- Edges:
|
|
34
|
+
- All nodes must be connected with -->.
|
|
35
|
+
- Edge labels (for conditions/annotations) must be written as |text| between nodes.
|
|
36
|
+
- Simplification Rule:
|
|
37
|
+
- If you cannot generate a model that fully meets all requirements due to the complexity of the description, you must simplify the model until it fully satisfies every requirement.
|
|
38
|
+
|
|
39
|
+
### Validation Procedure Summary:
|
|
40
|
+
When validating a Mermaid BPMN graph against the above rules, apply these steps systematically:
|
|
41
|
+
|
|
42
|
+
1. **Basic Syntax Validation**
|
|
43
|
+
- Confirm the graph uses LR direction.
|
|
44
|
+
- Verify all nodes follow the `id:type:shape and label` format with unique integer IDs.
|
|
45
|
+
- Check every task and subprocess node has a non-empty descriptive label.
|
|
46
|
+
- Ensure node types are valid BPMN types.
|
|
47
|
+
|
|
48
|
+
2. **Connectivity Validation**
|
|
49
|
+
- Confirm all edges use `-->` syntax and connect valid existing nodes.
|
|
50
|
+
- Ensure exactly one start event and at least one end event exist.
|
|
51
|
+
- Verify the graph is connected: all nodes are reachable from start and lead to an end event.
|
|
52
|
+
|
|
53
|
+
3. **Gateway Structural Validation**
|
|
54
|
+
- Identify all gateways as splits (≥2 outgoing edges) or merges (≥2 incoming edges).
|
|
55
|
+
- Confirm every split gateway has a corresponding matching merge gateway of the same type.
|
|
56
|
+
- Ensure no implicit merges (e.g., branches merging into a gateway of a different type without an explicit merge).
|
|
57
|
+
- Verify all gateways are connected (no isolated gateways).
|
|
58
|
+
|
|
59
|
+
4. **Task and Subprocess Rules**
|
|
60
|
+
- Verify no empty task or subprocess nodes.
|
|
61
|
+
- Confirm tasks are not orphaned: they have both incoming and outgoing edges unless start/end tasks.
|
|
62
|
+
|
|
63
|
+
5. **Flow Semantics**
|
|
64
|
+
- Exclusive gateways must have at least two outgoing branches.
|
|
65
|
+
- Parallel gateways’ splits must be followed by matching merges before continuing.
|
|
66
|
+
- All paths must start at the start event and lead to an end event.
|
|
67
|
+
|
|
68
|
+
6. **Reused Nodes Validation**
|
|
69
|
+
- Each reused node must be fully re-declared (with id:type:shape and label), never referenced by ID only or shorthand.
|
|
70
|
+
|
|
71
|
+
7. **Simplification Rule**
|
|
72
|
+
- If any rule above fails, simplify the model by removing redundant gateways or tasks, adding missing merges, or merging sequential gateways until the model fully satisfies all rules.
|
|
73
|
+
|
|
74
|
+
Return only Mermaid.js code as plain text, without markdown formatting or explanation.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
You are a CPEE (Cloud Process Execution Engine) process model validator and repair assistant.
|
|
2
|
+
|
|
3
|
+
Task:
|
|
4
|
+
1. Analyze the provided CPEE XML model.
|
|
5
|
+
2. Detect structural, syntactic, and execution-related issues that would prevent execution.
|
|
6
|
+
3. Repair only the minimum necessary parts of the model.
|
|
7
|
+
4. Preserve the original process logic whenever possible.
|
|
8
|
+
5. Do not introduce new business behavior unless required for executability.
|
|
9
|
+
|
|
10
|
+
Validation guidelines:
|
|
11
|
+
* XML must be well-formed.
|
|
12
|
+
* All tags must be properly opened and closed.
|
|
13
|
+
* CPEE control-flow elements must be structurally valid.
|
|
14
|
+
* References, attributes, and conditions must be syntactically correct.
|
|
15
|
+
* Loops must be able to terminate.
|
|
16
|
+
* Manipulate steps must contain valid code.
|
|
17
|
+
* Choice/alternative structures must be executable.
|
|
18
|
+
* Remove redundant or invalid elements if they prevent execution.
|
|
19
|
+
* Keep identifiers unchanged unless a conflict exists.
|
|
20
|
+
|
|
21
|
+
Executability criteria:
|
|
22
|
+
A model is considered executable only if:
|
|
23
|
+
- It is valid XML.
|
|
24
|
+
- It contains no structural CPEE errors.
|
|
25
|
+
- All executable activities are valid.
|
|
26
|
+
- Runtime references are resolvable.
|
|
27
|
+
- Variables used in conditions or code are available before use.
|
|
28
|
+
- Control flow can be executed without structural deadlocks caused by invalid model constructs.
|
|
29
|
+
- Loops and termination logic are executable.
|
|
30
|
+
|
|
31
|
+
Output rules:
|
|
32
|
+
* If the model is already executable and no repair is required, output exactly: PERFECT
|
|
33
|
+
* Otherwise output only the repaired XML.
|
|
34
|
+
* Do not provide explanations, comments, markdown, code fences, or additional text.
|
|
35
|
+
* The response must contain either a single XML document or the word PERFECT.
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# This file is part of CPEE-LLM.
|
|
2
|
+
#
|
|
3
|
+
# CPEE-LLM is free software: you can redistribute it and/or modify it under the
|
|
4
|
+
# terms of the GNU Lesser General Public License as published by the Free
|
|
5
|
+
# Software Foundation, either version 3 of the License, or (at your option) any
|
|
6
|
+
# later version.
|
|
7
|
+
#
|
|
8
|
+
# CPEE-LLM is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
9
|
+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
10
|
+
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
|
11
|
+
# details.
|
|
12
|
+
#
|
|
13
|
+
# You should have received a copy of the GNU Lesser General Public License
|
|
14
|
+
# along with CPEE-LLM (file LICENSE in the main directory). If not, see
|
|
15
|
+
# <http://www.gnu.org/licenses/>.
|
|
16
|
+
|
|
17
|
+
require 'ruby_llm'
|
|
18
|
+
require 'typhoeus'
|
|
19
|
+
require 'json'
|
|
20
|
+
|
|
21
|
+
module CPEE
|
|
22
|
+
|
|
23
|
+
module LLM
|
|
24
|
+
|
|
25
|
+
# own llm error class
|
|
26
|
+
class LLMError < StandardError #{{{
|
|
27
|
+
attr_reader :http_response
|
|
28
|
+
def initialize(message = "Something went wrong", http_response = 500)
|
|
29
|
+
@http_response = http_response
|
|
30
|
+
super(message)
|
|
31
|
+
end
|
|
32
|
+
end #}}}
|
|
33
|
+
|
|
34
|
+
module RubyLLM_Requests
|
|
35
|
+
|
|
36
|
+
def connect_llm(myllm,llms) #{{{
|
|
37
|
+
chat = nil
|
|
38
|
+
RubyLLM.configure do |config|
|
|
39
|
+
config.request_timeout = llms[:request_timeout]
|
|
40
|
+
config.max_retries = llms[:max_retries]
|
|
41
|
+
|
|
42
|
+
llms[:connectors].each do |k,v|
|
|
43
|
+
if myllm =~ /#{k}/ && chat.nil?
|
|
44
|
+
chat = eval(v)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
if chat.nil?
|
|
49
|
+
raise LLMError.new("Selected LLM model does not exist or is not supported. Please, select another LLM model.", 400)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
return chat
|
|
53
|
+
end #}}}
|
|
54
|
+
|
|
55
|
+
def generate_content(myllm, system_prompt, user_prompt, max_tokens, temperature, llms) #{{{
|
|
56
|
+
chat = connect_llm(myllm,llms)
|
|
57
|
+
chat.with_instructions system_prompt
|
|
58
|
+
chat.with_temperature(temperature)
|
|
59
|
+
if max_tokens != 0
|
|
60
|
+
if myllm.include?("gemini")
|
|
61
|
+
chat.with_params(generationConfig:{maxOutputTokens: max_tokens})
|
|
62
|
+
elsif myllm.include?("gpt")
|
|
63
|
+
chat.with_params(max_completion_tokens: max_tokens)
|
|
64
|
+
else
|
|
65
|
+
chat.with_params(max_tokens: max_tokens)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
response = chat.ask user_prompt
|
|
69
|
+
return response.content
|
|
70
|
+
rescue Faraday::TimeoutError => e
|
|
71
|
+
raise LLMError.new(e.message, 504)
|
|
72
|
+
rescue Exception => e
|
|
73
|
+
raise LLMError.new(e.message, 500)
|
|
74
|
+
end #}}}
|
|
75
|
+
|
|
76
|
+
def generate_json_content(myllm,system_prompt,user_prompt,max_tokens,temperature,llms) #{{{
|
|
77
|
+
chat = connect_llm(myllm,llms)
|
|
78
|
+
|
|
79
|
+
#set parameters
|
|
80
|
+
chat.with_params(max_tokens: max_tokens,response_format:{type:'json_object'})
|
|
81
|
+
chat.with_instructions system_prompt
|
|
82
|
+
chat.with_temperature(temperature)
|
|
83
|
+
response = chat.ask user_prompt
|
|
84
|
+
#puts JSON.parse(response.content)
|
|
85
|
+
return response.content
|
|
86
|
+
rescue Faraday::TimeoutError => e
|
|
87
|
+
raise LLMError.new(e.message, 504)
|
|
88
|
+
rescue Exception => e
|
|
89
|
+
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
|
+
pp "here"
|
|
96
|
+
pp temperature
|
|
97
|
+
system_prompt = File.read(File.join(__dir__,"prompts/generate1.txt"))
|
|
98
|
+
user_prompt = "Consider following process description: #{user_input}. Generate a BPMN model in Mermaid.js format."
|
|
99
|
+
new_mermaid = generate_content(llm,system_prompt,user_prompt,max_tokens,temperature,llms)
|
|
100
|
+
return new_mermaid
|
|
101
|
+
end #}}}
|
|
102
|
+
|
|
103
|
+
def adapt_mermaid_model(llm, user_input, process_model, llms={}) #{{{
|
|
104
|
+
max_tokens = 4000
|
|
105
|
+
temperature = 0
|
|
106
|
+
system_prompt = File.read(File.join(__dir__,"prompts/apply.txt"))
|
|
107
|
+
user_prompt = "Consider following process model: #{process_model}. Update this process model according to provided changes #{user_input}."
|
|
108
|
+
new_mermaid = generate_content(llm,system_prompt,user_prompt,max_tokens,temperature,llms)
|
|
109
|
+
return new_mermaid
|
|
110
|
+
end #}}}
|
|
111
|
+
|
|
112
|
+
def adapt_xml_model(llm, user_input, process_model, api_specification, llms={}) #{{{
|
|
113
|
+
max_tokens = 20000
|
|
114
|
+
temperature = 0
|
|
115
|
+
system_prompt = File.read(File.join(__dir__,"prompts/adapt_xml.txt"))
|
|
116
|
+
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}."
|
|
117
|
+
new_cpee = generate_content(llm,system_prompt,user_prompt,max_tokens,temperature,llms)
|
|
118
|
+
return new_cpee
|
|
119
|
+
end #}}}
|
|
120
|
+
|
|
121
|
+
def generate_plain_text(llm, user_input, llms={}) #{{{
|
|
122
|
+
max_tokens = 4000
|
|
123
|
+
temperature = 0
|
|
124
|
+
system_prompt = File.read(File.join(__dir__,"prompts/describe.txt"))
|
|
125
|
+
user_prompt = "Consider following process process model: #{user_input}. Generate a text describing provided process description."
|
|
126
|
+
process_description = generate_content(llm,system_prompt,user_prompt,max_tokens,temperature,llms)
|
|
127
|
+
return process_description
|
|
128
|
+
end #}}}
|
|
129
|
+
|
|
130
|
+
def generate_generic_content(llm, user_input, system_prompt, json, temperature, llms={}) #{{{
|
|
131
|
+
max_tokens = 20000
|
|
132
|
+
temperature = temperature.nil? ? 0 : temperature.to_f
|
|
133
|
+
if json == 'true'
|
|
134
|
+
process_description = generate_json_content(llm,system_prompt,user_input,max_tokens,temperature,llms)
|
|
135
|
+
else
|
|
136
|
+
process_description = generate_content(llm,system_prompt,user_input,max_tokens,temperature,llms)
|
|
137
|
+
end
|
|
138
|
+
return process_description
|
|
139
|
+
end #}}}
|
|
140
|
+
|
|
141
|
+
def generate_dataflow_content(llm, mermaid_model, api_specification, llms={}) #{{{
|
|
142
|
+
max_tokens = 10000
|
|
143
|
+
temperature = 0.1
|
|
144
|
+
system_prompt = File.read(File.join(__dir__,"prompts/dataflow.txt"))
|
|
145
|
+
user_prompt = "Given process mode #{mermaid_model} and task specification #{api_specification} with endpoint data, define the execution context and return a JSON specification."
|
|
146
|
+
dataflow = generate_content(llm,system_prompt,user_prompt,max_tokens,temperature,llms)
|
|
147
|
+
return dataflow
|
|
148
|
+
end #}}}
|
|
149
|
+
|
|
150
|
+
def generate_endpoint_mermaid_model(llm, user_input, endpoints, llms={}) #{{{
|
|
151
|
+
max_tokens = 4000
|
|
152
|
+
temperature = 0.1
|
|
153
|
+
system_prompt = File.read(File.join(__dir__,"prompts/generate_enpoints.txt"))
|
|
154
|
+
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."
|
|
155
|
+
new_mermaid = generate_content(llm,system_prompt,user_prompt,max_tokens,temperature,llms)
|
|
156
|
+
return new_mermaid
|
|
157
|
+
end #}}}
|
|
158
|
+
|
|
159
|
+
def validate_xml_model(llm, cpee_model, llms={}) #{{{
|
|
160
|
+
max_tokens = 0
|
|
161
|
+
temperature = 0.1
|
|
162
|
+
system_prompt = File.read(File.join(__dir__,"prompts/validate_xml.txt"))
|
|
163
|
+
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."
|
|
164
|
+
repaired_cpee = generate_content(llm,system_prompt,user_prompt,max_tokens,temperature,llms)
|
|
165
|
+
return repaired_cpee
|
|
166
|
+
end #}}}
|
|
167
|
+
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
end
|
data/server/connect_gpt
ADDED
data/server/cpee-llm
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/usr/bin/ruby
|
|
2
|
+
#
|
|
3
|
+
# This file is part of CPEE-LLM.
|
|
4
|
+
#
|
|
5
|
+
# CPEE-LLM is free software: you can redistribute it and/or modify it under the
|
|
6
|
+
# terms of the GNU Lesser General Public License as published by the Free
|
|
7
|
+
# Software Foundation, either version 3 of the License, or (at your option) any
|
|
8
|
+
# later version.
|
|
9
|
+
#
|
|
10
|
+
# CPEE-LLM is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
11
|
+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
12
|
+
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
|
13
|
+
# details.
|
|
14
|
+
#
|
|
15
|
+
# You should have received a copy of the GNU Lesser General Public License
|
|
16
|
+
# along with CPEE-LLM (file LICENSE in the main directory). If not, see
|
|
17
|
+
# <http://www.gnu.org/licenses/>.
|
|
18
|
+
|
|
19
|
+
if File.exist?(File.join(__dir__,'..','lib','cpee','llm','implementation.rb'))
|
|
20
|
+
require_relative File.join(__dir__,'..','lib','cpee','llm','implementation')
|
|
21
|
+
elsif File.exist?(File.join(Dir.home,'Projects','cpee-llm','lib','cpee','llm','implementation.rb'))
|
|
22
|
+
require_relative File.join(Dir.home, 'Projects','cpee-llm','lib','cpee','llm','implementation')
|
|
23
|
+
else
|
|
24
|
+
require 'cpee/llm/implementation'
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
options = {
|
|
28
|
+
:host => 'localhost',
|
|
29
|
+
:port => 9297,
|
|
30
|
+
:secure => false,
|
|
31
|
+
:llms => {}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
Riddl::Server.new(CPEE::LLM::SERVER, options) do
|
|
35
|
+
accessible_description true
|
|
36
|
+
cross_site_xhr true
|
|
37
|
+
|
|
38
|
+
@riddl_opts[:llms][:connectors].each do |k,v|
|
|
39
|
+
@riddl_opts[:llms][:connectors][k] = File.read(v)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
use CPEE::LLM::implementation(@riddl_opts)
|
|
43
|
+
end.loop!
|
data/tools/cpee-llm
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/usr/bin/ruby
|
|
2
|
+
#
|
|
3
|
+
# This file is part of CPEE-LLM.
|
|
4
|
+
#
|
|
5
|
+
# CPEE-LLM is free software: you can redistribute it and/or modify it under the
|
|
6
|
+
# terms of the GNU Lesser General Public License as published by the Free
|
|
7
|
+
# Software Foundation, either version 3 of the License, or (at your option) any
|
|
8
|
+
# later version.
|
|
9
|
+
#
|
|
10
|
+
# CPEE-LLM is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
11
|
+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
12
|
+
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
|
13
|
+
# details.
|
|
14
|
+
#
|
|
15
|
+
# You should have received a copy of the GNU Lesser General Public License
|
|
16
|
+
# along with CPEE-LLM (file LICENSE in the main directory). If not, see
|
|
17
|
+
# <http://www.gnu.org/licenses/>.
|
|
18
|
+
|
|
19
|
+
curpath = __dir__
|
|
20
|
+
require 'rubygems'
|
|
21
|
+
require 'optparse'
|
|
22
|
+
require 'fileutils'
|
|
23
|
+
require 'xml/smart'
|
|
24
|
+
require 'yaml'
|
|
25
|
+
require 'typhoeus'
|
|
26
|
+
require 'stringio'
|
|
27
|
+
|
|
28
|
+
def wrap(s, width=78, indent=18, extra_indent=4) #{{{
|
|
29
|
+
lines = []
|
|
30
|
+
line, s = s[0..indent-2], s[indent..-1]
|
|
31
|
+
s.split(/\n/).each do |ss|
|
|
32
|
+
ss.split(/[ \t]+/).each do |word|
|
|
33
|
+
if line.size + word.size >= width
|
|
34
|
+
lines << line
|
|
35
|
+
line = (" " * (indent + extra_indent)) + word
|
|
36
|
+
else
|
|
37
|
+
line << " " << word
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
lines << line if line
|
|
41
|
+
line = (" " * (indent-1))
|
|
42
|
+
end
|
|
43
|
+
return lines.join "\n"
|
|
44
|
+
end #}}}
|
|
45
|
+
|
|
46
|
+
exname = File.basename($0)
|
|
47
|
+
|
|
48
|
+
ARGV.options { |opt|
|
|
49
|
+
opt.summary_indent = ' ' * 2
|
|
50
|
+
opt.summary_width = 11
|
|
51
|
+
opt.banner = "Usage:\n#{opt.summary_indent}#{exname} new [DIR] | cpui [DIR]\n"
|
|
52
|
+
opt.on("Options:")
|
|
53
|
+
opt.on("--help", "-h", "This text") { puts opt; exit }
|
|
54
|
+
opt.on("")
|
|
55
|
+
opt.on(wrap("new [DIR] scaffolds a sample llm service.",78,14,0))
|
|
56
|
+
opt.parse!
|
|
57
|
+
}
|
|
58
|
+
if (ARGV.length != 2)
|
|
59
|
+
puts ARGV.options
|
|
60
|
+
exit
|
|
61
|
+
else
|
|
62
|
+
command = ARGV[0]
|
|
63
|
+
dir = ARGV[1]
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
if command == 'new'
|
|
67
|
+
if !File.exist?(dir)
|
|
68
|
+
FileUtils.cp_r(File.join(curpath,'..','server'),dir)
|
|
69
|
+
else
|
|
70
|
+
puts 'Directory already exists.'
|
|
71
|
+
end
|
|
72
|
+
else
|
|
73
|
+
puts ARGV.options
|
|
74
|
+
end
|
data/tools/cpee-llm-tool
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/usr/bin/ruby
|
|
2
|
+
#
|
|
3
|
+
# This file is part of CPEE-LLM.
|
|
4
|
+
#
|
|
5
|
+
# CPEE-LLM is free software: you can redistribute it and/or modify it under the
|
|
6
|
+
# terms of the GNU Lesser General Public License as published by the Free
|
|
7
|
+
# Software Foundation, either version 3 of the License, or (at your option) any
|
|
8
|
+
# later version.
|
|
9
|
+
#
|
|
10
|
+
# CPEE-LLM is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
11
|
+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
12
|
+
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
|
13
|
+
# details.
|
|
14
|
+
#
|
|
15
|
+
# You should have received a copy of the GNU Lesser General Public License
|
|
16
|
+
# along with CPEE-LLM (file LICENSE in the main directory). If not, see
|
|
17
|
+
# <http://www.gnu.org/licenses/>.
|
|
18
|
+
|
|
19
|
+
require 'riddl/client'
|
|
20
|
+
require 'json'
|
|
21
|
+
require 'typhoeus'
|
|
22
|
+
|
|
23
|
+
# ./cpee-llm-tool.rb [new|adapt] [user_input] [instance_id] [llm] - last one (i.e., 'llm' is optional and default to 'geminin-2.5-flash-lite')
|
|
24
|
+
|
|
25
|
+
# e.g.,
|
|
26
|
+
# ./cpee-llm-tool.rb new 'The MPON sends the dismissal to the MPOO. The MPOO reviews the dismissal. The MPOO opposes the dismissal of MPON or the MPOO confirms the dismissal of the MPON.' 'geminin-2.0-flash' 1501
|
|
27
|
+
# ./cpee-llm-tool.rb adapt 'Add task A after dismissal review.' 'geminin-2.0-flash' 1501
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
srv = Riddl::Client.new('http://localhost:9297/')
|
|
31
|
+
status, res = srv.post [
|
|
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
|
+
Riddl::Parameter::Complex.new("user_input","text/plain",ARGV[1]),
|
|
34
|
+
Riddl::Parameter::Complex.new("llm","text/plain",ARGV[3].nil?() ? 'gemini-2.5-flash-light' : ARGV[3])
|
|
35
|
+
]
|
|
36
|
+
if status >= 200 && status < 300
|
|
37
|
+
res
|
|
38
|
+
else
|
|
39
|
+
raise "llm did not work"
|
|
40
|
+
end
|
|
41
|
+
description = JSON.parse(res[0].value().read())['output_cpee']
|
|
42
|
+
|
|
43
|
+
srv = Riddl::Client.new("https://cpee.org/flow/engine/#{ARGV[2]}/properties/dslx/")
|
|
44
|
+
status, res = srv.put [
|
|
45
|
+
Riddl::Parameter::Complex.new("dslx","text/xml",description)
|
|
46
|
+
]
|
|
47
|
+
if status >= 200 && status < 300
|
|
48
|
+
res
|
|
49
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: cpee-llm
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Nataliia Klievtsova
|
|
8
|
+
- Matthias Ehrendorfer
|
|
9
|
+
- Juergen eTM Mangler
|
|
10
|
+
bindir: tools
|
|
11
|
+
cert_chain: []
|
|
12
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
13
|
+
dependencies:
|
|
14
|
+
- !ruby/object:Gem::Dependency
|
|
15
|
+
name: riddl
|
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
|
17
|
+
requirements:
|
|
18
|
+
- - "~>"
|
|
19
|
+
- !ruby/object:Gem::Version
|
|
20
|
+
version: '1.0'
|
|
21
|
+
type: :runtime
|
|
22
|
+
prerelease: false
|
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
24
|
+
requirements:
|
|
25
|
+
- - "~>"
|
|
26
|
+
- !ruby/object:Gem::Version
|
|
27
|
+
version: '1.0'
|
|
28
|
+
- !ruby/object:Gem::Dependency
|
|
29
|
+
name: json
|
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
|
31
|
+
requirements:
|
|
32
|
+
- - "~>"
|
|
33
|
+
- !ruby/object:Gem::Version
|
|
34
|
+
version: '2.10'
|
|
35
|
+
type: :runtime
|
|
36
|
+
prerelease: false
|
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
38
|
+
requirements:
|
|
39
|
+
- - "~>"
|
|
40
|
+
- !ruby/object:Gem::Version
|
|
41
|
+
version: '2.10'
|
|
42
|
+
- !ruby/object:Gem::Dependency
|
|
43
|
+
name: xml-smart
|
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
|
45
|
+
requirements:
|
|
46
|
+
- - "~>"
|
|
47
|
+
- !ruby/object:Gem::Version
|
|
48
|
+
version: '0.4'
|
|
49
|
+
type: :runtime
|
|
50
|
+
prerelease: false
|
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
52
|
+
requirements:
|
|
53
|
+
- - "~>"
|
|
54
|
+
- !ruby/object:Gem::Version
|
|
55
|
+
version: '0.4'
|
|
56
|
+
- !ruby/object:Gem::Dependency
|
|
57
|
+
name: typhoeus
|
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
|
59
|
+
requirements:
|
|
60
|
+
- - "~>"
|
|
61
|
+
- !ruby/object:Gem::Version
|
|
62
|
+
version: '1.4'
|
|
63
|
+
type: :runtime
|
|
64
|
+
prerelease: false
|
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
66
|
+
requirements:
|
|
67
|
+
- - "~>"
|
|
68
|
+
- !ruby/object:Gem::Version
|
|
69
|
+
version: '1.4'
|
|
70
|
+
- !ruby/object:Gem::Dependency
|
|
71
|
+
name: ruby_llm
|
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
|
73
|
+
requirements:
|
|
74
|
+
- - "~>"
|
|
75
|
+
- !ruby/object:Gem::Version
|
|
76
|
+
version: '1.15'
|
|
77
|
+
type: :runtime
|
|
78
|
+
prerelease: false
|
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
80
|
+
requirements:
|
|
81
|
+
- - "~>"
|
|
82
|
+
- !ruby/object:Gem::Version
|
|
83
|
+
version: '1.15'
|
|
84
|
+
- !ruby/object:Gem::Dependency
|
|
85
|
+
name: rag_embeddings
|
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
|
87
|
+
requirements:
|
|
88
|
+
- - "~>"
|
|
89
|
+
- !ruby/object:Gem::Version
|
|
90
|
+
version: '0'
|
|
91
|
+
type: :runtime
|
|
92
|
+
prerelease: false
|
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
94
|
+
requirements:
|
|
95
|
+
- - "~>"
|
|
96
|
+
- !ruby/object:Gem::Version
|
|
97
|
+
version: '0'
|
|
98
|
+
description: see http://cpee.org
|
|
99
|
+
email: n.klievtsova@gmail.com
|
|
100
|
+
executables:
|
|
101
|
+
- cpee-llm
|
|
102
|
+
extensions: []
|
|
103
|
+
extra_rdoc_files:
|
|
104
|
+
- README.md
|
|
105
|
+
files:
|
|
106
|
+
- AUTHORS
|
|
107
|
+
- LICENSE
|
|
108
|
+
- README.md
|
|
109
|
+
- Rakefile
|
|
110
|
+
- cpee-llm.gemspec
|
|
111
|
+
- lib/cpee/llm/dataflow.rb
|
|
112
|
+
- lib/cpee/llm/functions.rb
|
|
113
|
+
- lib/cpee/llm/implementation.rb
|
|
114
|
+
- lib/cpee/llm/implementation.xml
|
|
115
|
+
- lib/cpee/llm/prompts/adapt_xml.txt
|
|
116
|
+
- lib/cpee/llm/prompts/apply.txt
|
|
117
|
+
- lib/cpee/llm/prompts/dataflow.txt
|
|
118
|
+
- lib/cpee/llm/prompts/derive.txt
|
|
119
|
+
- lib/cpee/llm/prompts/describe.txt
|
|
120
|
+
- lib/cpee/llm/prompts/gemini-request.json
|
|
121
|
+
- lib/cpee/llm/prompts/generate1.txt
|
|
122
|
+
- lib/cpee/llm/prompts/generate_enpoints.txt
|
|
123
|
+
- lib/cpee/llm/prompts/generate_enpoints1.txt
|
|
124
|
+
- lib/cpee/llm/prompts/identify.txt
|
|
125
|
+
- lib/cpee/llm/prompts/validate_mermaid.xml
|
|
126
|
+
- lib/cpee/llm/prompts/validate_xml.txt
|
|
127
|
+
- lib/cpee/llm/rubyllm_requests.rb
|
|
128
|
+
- server/connect_gemini
|
|
129
|
+
- server/connect_gpt
|
|
130
|
+
- server/connect_morpheus
|
|
131
|
+
- server/cpee-llm
|
|
132
|
+
- server/cpee-llm.conf
|
|
133
|
+
- tools/cpee-llm
|
|
134
|
+
- tools/cpee-llm-tool
|
|
135
|
+
homepage: http://cpee.org/
|
|
136
|
+
licenses:
|
|
137
|
+
- LGPL-3.0-or-later
|
|
138
|
+
metadata: {}
|
|
139
|
+
rdoc_options: []
|
|
140
|
+
require_paths:
|
|
141
|
+
- lib
|
|
142
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
143
|
+
requirements:
|
|
144
|
+
- - ">="
|
|
145
|
+
- !ruby/object:Gem::Version
|
|
146
|
+
version: '3.4'
|
|
147
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
148
|
+
requirements:
|
|
149
|
+
- - ">="
|
|
150
|
+
- !ruby/object:Gem::Version
|
|
151
|
+
version: '0'
|
|
152
|
+
requirements: []
|
|
153
|
+
rubygems_version: 3.6.9
|
|
154
|
+
specification_version: 4
|
|
155
|
+
summary: CPEE Conversational Agents
|
|
156
|
+
test_files: []
|