cpee-llm 1.0.6 → 1.2.2

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.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +668 -159
  3. data/README.md +15 -0
  4. data/cpee-llm.gemspec +3 -3
  5. data/lib/cpee/llm/dataflow.rb +3 -3
  6. data/lib/cpee/llm/functions.rb +80 -77
  7. data/lib/cpee/llm/implementation.rb +43 -17
  8. data/lib/cpee/llm/implementation.xml +41 -7
  9. data/lib/cpee/llm/prompts/system/adapt_mermaid.txt +12 -0
  10. data/lib/cpee/llm/prompts/system/adapt_xml_documentation.txt +50 -0
  11. data/lib/cpee/llm/prompts/system/adapt_xml_endpoints.txt +80 -0
  12. data/lib/cpee/llm/prompts/{dataflow.txt → system/dataflow.txt} +13 -25
  13. data/lib/cpee/llm/prompts/system/fragments/cpee_xml/arguments.txt +8 -0
  14. data/lib/cpee/llm/prompts/system/fragments/cpee_xml/color_palette.txt +10 -0
  15. data/lib/cpee/llm/prompts/system/fragments/cpee_xml/description.txt +3 -0
  16. data/lib/cpee/llm/prompts/system/fragments/cpee_xml/documentation.txt +35 -0
  17. data/lib/cpee/llm/prompts/system/fragments/cpee_xml/exclusive_gateway.txt +7 -0
  18. data/lib/cpee/llm/prompts/system/fragments/cpee_xml/finalize.txt +2 -0
  19. data/lib/cpee/llm/prompts/system/fragments/cpee_xml/inclusive_gateway.txt +2 -0
  20. data/lib/cpee/llm/prompts/system/fragments/cpee_xml/loop.txt +7 -0
  21. data/lib/cpee/llm/prompts/system/fragments/cpee_xml/method.txt +6 -0
  22. data/lib/cpee/llm/prompts/system/fragments/cpee_xml/parallel_gateway.txt +6 -0
  23. data/lib/cpee/llm/prompts/system/fragments/cpee_xml/pause.txt +4 -0
  24. data/lib/cpee/llm/prompts/system/fragments/cpee_xml/pause_insertion.txt +3 -0
  25. data/lib/cpee/llm/prompts/system/fragments/cpee_xml/script_task.txt +5 -0
  26. data/lib/cpee/llm/prompts/system/fragments/cpee_xml/sequence.txt +2 -0
  27. data/lib/cpee/llm/prompts/system/fragments/cpee_xml/service_task.txt +20 -0
  28. data/lib/cpee/llm/prompts/system/fragments/cpee_xml/variables.txt +3 -0
  29. data/lib/cpee/llm/prompts/system/fragments/cpee_xml.txt +15 -0
  30. data/lib/cpee/llm/prompts/system/fragments/data_references.txt +14 -0
  31. data/lib/cpee/llm/prompts/system/fragments/endpoint_naming.txt +1 -0
  32. data/lib/cpee/llm/prompts/system/fragments/mermaid/structure_rules.txt +29 -0
  33. data/lib/cpee/llm/prompts/system/fragments/mermaid/syntax.txt +22 -0
  34. data/lib/cpee/llm/prompts/system/fragments/numeric_conversion.txt +5 -0
  35. data/lib/cpee/llm/prompts/system/fragments/service_registry.txt +6 -0
  36. data/lib/cpee/llm/prompts/system/fragments/unmatched_tasks.txt +4 -0
  37. data/lib/cpee/llm/prompts/system/generate_mermaid.txt +40 -0
  38. data/lib/cpee/llm/prompts/system/generate_mermaid_endpoints.txt +82 -0
  39. data/lib/cpee/llm/prompts/system/intent.txt +45 -0
  40. data/lib/cpee/llm/prompts/{validate_xml.txt → system/validate_xml.txt} +15 -0
  41. data/lib/cpee/llm/prompts/user/adapt.txt +8 -0
  42. data/lib/cpee/llm/prompts/user/adapt_xml_endpoints.txt +11 -0
  43. data/lib/cpee/llm/prompts/user/dataflow.txt +9 -0
  44. data/lib/cpee/llm/prompts/user/describe_text.txt +4 -0
  45. data/lib/cpee/llm/prompts/user/generate_mermaid.txt +5 -0
  46. data/lib/cpee/llm/prompts/user/generate_mermaid_endpoints.txt +9 -0
  47. data/lib/cpee/llm/prompts/user/intent.txt +17 -0
  48. data/lib/cpee/llm/prompts/user/validate_xml.txt +5 -0
  49. data/lib/cpee/llm/rubyllm_requests.rb +71 -119
  50. data/server/connect_gemini +1 -1
  51. data/server/connect_gpt +1 -1
  52. data/server/connect_morpheus +1 -1
  53. data/server/{cpee-llm → llm} +5 -4
  54. data/server/plugins.json +51 -0
  55. data/tools/cpee-llm +3 -3
  56. data/tools/cpee-llm-tool +4 -4
  57. metadata +46 -17
  58. data/lib/cpee/llm/prompts/adapt_docxml_description.txt +0 -131
  59. data/lib/cpee/llm/prompts/adapt_xml_endpoints.txt +0 -157
  60. data/lib/cpee/llm/prompts/apply.txt +0 -32
  61. data/lib/cpee/llm/prompts/derive.txt +0 -28
  62. data/lib/cpee/llm/prompts/gemini-request.json +0 -18
  63. data/lib/cpee/llm/prompts/generate1.txt +0 -90
  64. data/lib/cpee/llm/prompts/generate_enpoints.txt +0 -132
  65. data/lib/cpee/llm/prompts/generate_enpoints1.txt +0 -155
  66. data/lib/cpee/llm/prompts/identify.txt +0 -25
  67. data/lib/cpee/llm/prompts/validate_mermaid.xml +0 -74
  68. /data/lib/cpee/llm/prompts/{describe.txt → system/describe_text.txt} +0 -0
  69. /data/server/{cpee-llm.conf → llm.conf} +0 -0
data/README.md CHANGED
@@ -152,6 +152,7 @@ Performs arbitrary LLM tasks using a system prompt and user input.
152
152
  | system_prompt | text/plain |
153
153
  | format | text/plain (`true`/`false`) |
154
154
  | temperature | text/plain (optional) |
155
+ | documents | `*/*` (optional, repeatable) |
155
156
 
156
157
  ## Response
157
158
 
@@ -168,6 +169,7 @@ Performs arbitrary LLM tasks using a system prompt and user input.
168
169
  ### Notes
169
170
 
170
171
  - `format=true` requests JSON output (guarantees valid JSON but not any specific structure).
172
+ - `documents` can be repeated to attach one or more files (e.g. images, PDFs, office documents, plain text) to the request, sent as multipart file parts. Attachments are passed through to the LLM alongside `user_input`; support depends on the selected model/provider.
171
173
 
172
174
  List of supporteb providers: https://rubyllm.com/chat/#getting-structured-output
173
175
 
@@ -182,4 +184,17 @@ curl -X POST https://cpee.org/llm/generic/ \
182
184
  -F "format=false;type=text/plain"
183
185
  ```
184
186
 
187
+ With attached documents:
188
+
189
+ ```bash
190
+ curl -X POST https://cpee.org/llm/generic/ \
191
+ -H 'Content-Type:multipart/form-data' \
192
+ -F "llm=gemini-2.5-flash-lite;type=text/plain" \
193
+ -F "user_input=Summarize the attached document.;type=text/plain" \
194
+ -F "system_prompt=Return the summary as bullet points.;type=text/plain" \
195
+ -F "format=false;type=text/plain" \
196
+ -F "documents=@report.pdf;type=application/pdf" \
197
+ -F "documents=@chart.png;type=image/png"
198
+ ```
199
+
185
200
  ---
data/cpee-llm.gemspec CHANGED
@@ -1,13 +1,13 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "cpee-llm"
3
- s.version = "1.0.6"
3
+ s.version = "1.2.2"
4
4
  s.platform = Gem::Platform::RUBY
5
- s.license = "LGPL-3.0-or-later"
5
+ s.license = "GPL-3.0-or-later"
6
6
  s.summary = "CPEE Conversational Agents"
7
7
 
8
8
  s.description = "see http://cpee.org"
9
9
 
10
- s.files = Dir['{server/*,tools/**/*,lib/**/*}'] + %w(LICENSE Rakefile cpee-llm.gemspec README.md AUTHORS)
10
+ s.files = Dir['{server/*,tools/**/*,lib/**/*}'] - Dir['lib/cpee/llm/prompts/legacy{,/**/*}'] + %w(LICENSE Rakefile cpee-llm.gemspec README.md AUTHORS)
11
11
  s.require_path = 'lib'
12
12
  s.extra_rdoc_files = ['README.md']
13
13
  s.bindir = 'tools'
@@ -1,16 +1,16 @@
1
1
  # This file is part of CPEE-LLM.
2
2
  #
3
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
4
+ # terms of the GNU General Public License as published by the Free
5
5
  # Software Foundation, either version 3 of the License, or (at your option) any
6
6
  # later version.
7
7
  #
8
8
  # CPEE-LLM is distributed in the hope that it will be useful, but WITHOUT ANY
9
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
10
+ # A PARTICULAR PURPOSE. See the GNU General Public License for more
11
11
  # details.
12
12
  #
13
- # You should have received a copy of the GNU Lesser General Public License
13
+ # You should have received a copy of the GNU General Public License
14
14
  # along with CPEE-LLM (file LICENSE in the main directory). If not, see
15
15
  # <http://www.gnu.org/licenses/>.
16
16
 
@@ -1,16 +1,16 @@
1
1
  # This file is part of CPEE-LLM.
2
2
  #
3
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
4
+ # terms of the GNU General Public License as published by the Free
5
5
  # Software Foundation, either version 3 of the License, or (at your option) any
6
6
  # later version.
7
7
  #
8
8
  # CPEE-LLM is distributed in the hope that it will be useful, but WITHOUT ANY
9
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
10
+ # A PARTICULAR PURPOSE. See the GNU General Public License for more
11
11
  # details.
12
12
  #
13
- # You should have received a copy of the GNU Lesser General Public License
13
+ # You should have received a copy of the GNU General Public License
14
14
  # along with CPEE-LLM (file LICENSE in the main directory). If not, see
15
15
  # <http://www.gnu.org/licenses/>.
16
16
 
@@ -45,15 +45,9 @@ module CPEE
45
45
  trans.generate_model(CPEE::Transformation::Target::CPEE)
46
46
  end #}}}
47
47
 
48
- def generate_model(myllm,user_input,temperature,llms) #{{{
48
+ def error_handler #{{{
49
49
  begin
50
- llm_response = generate_mermaid_model(myllm,user_input,temperature,llms)
51
- # raise exceptions if response is empty for some reason
52
- if llm_response.nil? || llm_response.empty?
53
- raise LLMError.new("Something went wrong and your content was not generated!", 500)
54
- else
55
- return llm_response
56
- end
50
+ yield
57
51
  rescue LLMError => e_llm
58
52
  e_llm.message
59
53
  raise e_llm
@@ -63,28 +57,42 @@ module CPEE
63
57
  end
64
58
  end #}}}
65
59
 
60
+ def generate_model(myllm,user_input,temperature,llms) #{{{
61
+ error_handler do
62
+ system_prompt = build_system_prompt("generate_mermaid.txt")
63
+ user_prompt = build_user_prompt("generate_mermaid.txt", user_input:)
64
+ llm_response = generate_content(myllm,system_prompt,user_prompt,4000,temperature,llms)
65
+ # raise exceptions if response is empty for some reason
66
+ if llm_response.nil? || llm_response.empty?
67
+ raise LLMError.new("Something went wrong and your content was not generated!", 500)
68
+ else
69
+ return llm_response
70
+ end
71
+ end
72
+ end #}}}
73
+
66
74
  def adapt_model(myllm,doc,user_input,llms) #{{{
67
75
  input_cpee = doc.to_s()
68
76
  input_mermaid = cpee_to_mermaid(doc.to_s())
69
- begin
70
- llm_response = adapt_mermaid_model(myllm,user_input,input_mermaid,llms)
77
+ error_handler do
78
+ system_prompt = build_system_prompt("adapt_mermaid.txt")
79
+ user_prompt = build_user_prompt("adapt.txt", user_input:, process_model: input_mermaid)
80
+ llm_response = generate_content(myllm,system_prompt,user_prompt,4000,0,llms)
71
81
  # raise exceptions if response is empty for some reason
72
82
  if llm_response.nil? || llm_response.empty?
73
83
  raise LLMError.new("Something went wrong and your content was not generated!", 500)
74
84
  else
75
85
  return llm_response
76
86
  end
77
- rescue LLMError => e_llm
78
- raise e_llm
79
- rescue Exception => e
80
- raise e
81
87
  end
82
88
  end #}}}
83
89
 
84
90
  def adapt_doccpee_description(myllm,doc,user_input,llms) #{{{
85
91
  input_cpee = doc.to_s()
86
- begin
87
- llm_response = adapt_docxml_description(myllm,user_input,input_cpee,llms)
92
+ error_handler do
93
+ system_prompt = build_system_prompt("adapt_xml_documentation.txt")
94
+ user_prompt = build_user_prompt("adapt.txt", user_input:, process_model: input_cpee)
95
+ llm_response = generate_content(myllm,system_prompt,user_prompt,16000,0,llms)
88
96
  # raise exceptions if response is empty for some reason
89
97
  if llm_response.nil? || llm_response.empty?
90
98
  raise LLMError.new("Something went wrong and your content was not generated!", 500)
@@ -100,27 +108,20 @@ module CPEE
100
108
  end
101
109
  return llm_response
102
110
  end
103
- rescue LLMError => e_llm
104
- raise e_llm
105
- rescue Exception => e
106
- raise e
107
111
  end
108
112
  end #}}}
109
113
 
110
114
  def adapt_cpee_model(myllm,doc,user_input,existing_endpoints,endpoints,llms) #{{{
111
- testset = XML::Smart.string(<<~XML)
112
- <testset xmlns="http://cpee.org/ns/properties/2.0">
113
- </testset>
114
- XML
115
+ testset = XML::Smart.string('<testset xmlns="http://cpee.org/ns/properties/2.0"></testset>')
115
116
  root = testset.root
116
117
  root.add(existing_endpoints.root)
117
118
  dslx = root.add("dslx")
118
119
  dslx.add(doc.root)
119
120
 
120
- #puts testset.to_s
121
-
122
- begin
123
- llm_response = adapt_xml_model(myllm,user_input,testset,endpoints,llms)
121
+ error_handler do
122
+ system_prompt = build_system_prompt("adapt_xml_endpoints.txt")
123
+ user_prompt = build_user_prompt("adapt_xml_endpoints.txt", user_input:, process_model: testset, api_specification: endpoints)
124
+ llm_response = generate_content(myllm,system_prompt,user_prompt,15000,0,llms)
124
125
  # raise exceptions if response is empty for some reason
125
126
  if llm_response.nil? || llm_response.empty?
126
127
  raise LLMError.new("Something went wrong and your content was not generated!", 500)
@@ -136,54 +137,42 @@ module CPEE
136
137
  end
137
138
  return llm_response
138
139
  end
139
- rescue LLMError => e_llm
140
- raise e_llm
141
- rescue Exception => e
142
- raise e
143
140
  end
144
141
  end #}}}
145
142
 
146
143
  def generate_text(myllm,doc,llms) #{{{
147
144
  input_cpee = doc.to_s()
148
145
  input_mermaid = cpee_to_mermaid(doc.to_s())
149
- begin
150
- llm_response = generate_plain_text(myllm,input_mermaid,llms)
146
+ error_handler do
147
+ system_prompt = build_system_prompt("describe_text.txt")
148
+ user_prompt = build_user_prompt("describe_text.txt", user_input: input_mermaid)
149
+ llm_response = generate_content(myllm,system_prompt,user_prompt,4000,0,llms)
151
150
  # raise exceptions if response is empty for some reason
152
151
  if llm_response.nil? || llm_response.empty?
153
152
  raise LLMError.new("Something went wrong and your content was not generated!", 500)
154
153
  else
155
154
  return llm_response
156
155
  end
157
- rescue LLMError => e_llm
158
- e_llm.message
159
- raise e_llm
160
- rescue Exception => e
161
- e.message
162
- raise e
163
156
  end
164
157
  end #}}}
165
158
 
166
- def generate_generic(myllm,user_input,system_prompt,format,temperature,llms) #{{{
167
- begin
168
- llm_response = generate_generic_content(myllm, user_input, system_prompt, format, temperature, llms)
159
+ def generate_generic(myllm,user_input,system_prompt,format,temperature,documents,llms) #{{{
160
+ error_handler do
161
+ llm_response = generate_content(myllm, system_prompt, user_input, 16000, temperature, llms, format == 'true' ? { json: true } : {}, documents)
169
162
  # raise exceptions if response is empty for some reason
170
163
  if llm_response.nil? || llm_response.empty?
171
164
  raise LLMError.new("Something went wrong and your content was not generated!", 500)
172
165
  else
173
166
  return llm_response
174
167
  end
175
- rescue LLMError => e_llm
176
- e_llm.message
177
- raise e_llm
178
- rescue Exception => e
179
- e.message
180
- raise e
181
168
  end
182
169
  end #}}}
183
170
 
184
171
  def generate_dataflow(myllm,mermaid_model,api_specification,llms) #{{{
185
- begin
186
- llm_response = generate_dataflow_content(myllm, mermaid_model, api_specification, llms)
172
+ error_handler do
173
+ system_prompt = build_system_prompt("dataflow.txt")
174
+ user_prompt = build_user_prompt("dataflow.txt", mermaid_model:, api_specification:)
175
+ llm_response = generate_content(myllm, system_prompt, user_prompt, 4000, 0.1, llms)
187
176
  # raise exceptions if response is empty for some reason
188
177
  if llm_response.nil? || llm_response.empty?
189
178
  raise LLMError.new("Something went wrong and your content was not generated!", 500)
@@ -201,36 +190,28 @@ module CPEE
201
190
  end
202
191
  return llm_response
203
192
  end
204
- rescue LLMError => e_llm
205
- e_llm.message
206
- raise e_llm
207
- rescue Exception => e
208
- e.message
209
- raise e
210
193
  end
211
194
  end #}}}
212
195
 
213
196
  def generate_endpoint_model(myllm,user_input,endpoints,llms) #{{{
214
- begin
215
- llm_response = generate_endpoint_mermaid_model(myllm,user_input,endpoints,llms)
197
+ error_handler do
198
+ system_prompt = build_system_prompt("generate_mermaid_endpoints.txt")
199
+ user_prompt = build_user_prompt("generate_mermaid_endpoints.txt", user_input:, endpoints:)
200
+ llm_response = generate_content(myllm,system_prompt,user_prompt,4000,0.1,llms)
216
201
  # raise exceptions if response is empty for some reason
217
202
  if llm_response.nil? || llm_response.empty?
218
203
  raise LLMError.new("Something went wrong and your content was not generated!", 500)
219
204
  else
220
205
  return llm_response
221
206
  end
222
- rescue LLMError => e_llm
223
- e_llm.message
224
- raise e_llm
225
- rescue Exception => e
226
- e.message
227
- raise e
228
207
  end
229
208
  end #}}}
230
209
 
231
210
  def validate_cpee_model(myllm,cpee_model,llms) #{{{
232
- begin
233
- llm_response = validate_xml_model(myllm,cpee_model,llms)
211
+ error_handler do
212
+ system_prompt = build_system_prompt("validate_xml.txt")
213
+ user_prompt = build_user_prompt("validate_xml.txt", cpee_model:)
214
+ llm_response = generate_content(myllm,system_prompt,user_prompt,0,0.1,llms)
234
215
  if llm_response.nil? || llm_response.empty?
235
216
  raise LLMError.new("Something went wrong and your content was not generated!", 500)
236
217
  elsif llm_response.strip.downcase == "perfect"
@@ -243,16 +224,38 @@ module CPEE
243
224
  begin
244
225
  XML::Smart.string(llm_response)
245
226
  rescue Nokogiri::XML::SyntaxError => e
246
- raise LLMError.new("Something went wrong and llm was not able to generate valid xml model", llm_response)
227
+ raise LLMError.new("Something went wrong and llm was not able to generate valid xml model", 500)
247
228
  end
248
229
  return llm_response
249
230
  end
250
- rescue LLMError => e_llm
251
- e_llm.message
252
- raise e_llm
253
- rescue Exception => e
254
- e.message
255
- raise e
231
+ end
232
+ end #}}}
233
+
234
+ def guess_intent(myllm,user_input,plugins,llms) #{{{
235
+ plugs = File.read(plugins)
236
+ error_handler do
237
+ system_prompt = build_system_prompt("intent.txt")
238
+ user_prompt = build_user_prompt("intent.txt", user_input:, plugins: plugs)
239
+ response = generate_content(myllm,system_prompt,user_prompt,4000,0.1,llms,{ json: true })
240
+ if response.nil? || response.empty?
241
+ raise LLMError.new("Something went wrong and your content was not generated!", 500)
242
+ else
243
+ result = JSON::parse(response)
244
+ if result.is_a?(Hash) && result["id"]
245
+ plugin_list = JSON::parse(plugs)
246
+ plugin = plugin_list.find { |p| p["id"] == result["id"] }
247
+ if plugin
248
+ plugin.each do |k,v|
249
+ result[k] = v unless k == "description"
250
+ end
251
+ result
252
+ else
253
+ nil
254
+ end
255
+ else
256
+ result
257
+ end
258
+ end
256
259
  end
257
260
  end #}}}
258
261
 
@@ -1,16 +1,16 @@
1
1
  # This file is part of CPEE-LLM.
2
2
  #
3
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
4
+ # terms of the GNU General Public License as published by the Free
5
5
  # Software Foundation, either version 3 of the License, or (at your option) any
6
6
  # later version.
7
7
  #
8
8
  # CPEE-LLM is distributed in the hope that it will be useful, but WITHOUT ANY
9
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
10
+ # A PARTICULAR PURPOSE. See the GNU General Public License for more
11
11
  # details.
12
12
  #
13
- # You should have received a copy of the GNU Lesser General Public License
13
+ # You should have received a copy of the GNU General Public License
14
14
  # along with CPEE-LLM (file LICENSE in the main directory). If not, see
15
15
  # <http://www.gnu.org/licenses/>.
16
16
 
@@ -41,7 +41,6 @@ module CPEE
41
41
  temperature = @p.shift.value.read if @p[0]&.name == 'temperature'
42
42
 
43
43
  doc = XML::Smart.string(input_cpee)
44
- pp prompt_type
45
44
  begin
46
45
  output_cpee = if prompt_type == 'generate_noendpoints' || prompt_type == 'generate_noendpoints_docdescription'
47
46
  llm_response = generate_model(myllm,user_input,temperature,llms)
@@ -64,7 +63,7 @@ module CPEE
64
63
  return Riddl::Parameter::Complex.new('llm_out', 'application/json', { error: e }.to_json)
65
64
  end
66
65
 
67
- return(Riddl::Parameter::Complex.new("llm_out","application/json",{:user_input => user_input, :used_llm => myllm, :input_cpee => input_cpee, :input_intermediate => doc.root().empty?() ? "" : cpee_to_mermaid(doc.to_s()), :output_intermediate => llm_response, :output_cpee => output_cpee, :status => "Success"}.to_json()))
66
+ return Riddl::Parameter::Complex.new("llm_out","application/json",{:user_input => user_input, :used_llm => myllm, :input_cpee => input_cpee, :input_intermediate => doc.root().empty?() ? "" : cpee_to_mermaid(doc.to_s()), :output_intermediate => llm_response, :output_cpee => output_cpee, :status => "Success"}.to_json())
68
67
  rescue LLMError => e
69
68
  @status = e&.http_response || 400
70
69
  return Riddl::Parameter::Complex.new("llm_out","application/json",{ :error => "#{prompt_type} #{e.message}"}.to_json())
@@ -115,18 +114,20 @@ module CPEE
115
114
  llms = @a[0]
116
115
  #get parameters
117
116
  begin
118
- myllm = @p[0].value.read
119
- user_input = @p[1].value.read
120
- system_prompt = @p[2].value.read
121
- format = @p[3].value.read
122
- temperature = @p[4]&.value&.read
117
+ myllm = @p.shift.value.read
118
+ user_input = @p.shift.value.read
119
+ system_prompt = @p.shift.value.read
120
+ format = @p.shift.value.read
121
+ temperature = @p.shift.value.read if @p[0]&.name == 'temperature'
122
+ documents = []
123
+ documents << @p.shift while @p[0]&.name == 'document'
123
124
  rescue Exception => e
124
125
  @status = 400
125
126
  return Riddl::Parameter::Complex.new("generic_out","application/json",{:error => e}.to_json())
126
127
  end
127
128
 
128
129
  begin
129
- llm_response = generate_generic(myllm,user_input,system_prompt,format,temperature,llms)
130
+ llm_response = generate_generic(myllm,user_input,system_prompt,format,temperature,documents,llms)
130
131
  rescue LLMError => e
131
132
  @status = e.http_response
132
133
  return Riddl::Parameter::Complex.new("generic_out","application/json",{:error => e.message}.to_json())
@@ -198,36 +199,61 @@ module CPEE
198
199
  llm_response = validate_cpee_model(myllm,input_cpee,llms)
199
200
  rescue LLMError => e
200
201
  @status = e.http_response
201
- return Riddl::Parameter::Complex.new("generic_out","application/json",{:error => e.message}.to_json())
202
+ return Riddl::Parameter::Complex.new("llm_out","application/json",{:error => e.message}.to_json())
202
203
  end
203
204
 
204
205
  return(Riddl::Parameter::Complex.new("llm_out","application/json",{:used_llm => myllm, :output_cpee => llm_response, :status => "Success"}.to_json()))
205
206
  end
206
207
  end #}}}
207
208
 
209
+ class GuessIntent < Riddl::Implementation #{{{
210
+ include Functions
211
+
212
+ def response
213
+ llms = @a[0]
214
+ plugins = @a[1]
215
+
216
+ input_cpee = @p[0].value.read
217
+ myllm = @p[1].value.read
218
+
219
+ begin
220
+ response = guess_intent(myllm,input_cpee,plugins,llms)
221
+ rescue LLMError => e
222
+ @status = e.http_response
223
+ return Riddl::Parameter::Complex.new("user_intent","application/json",{:error => e.message}.to_json())
224
+ end
225
+
226
+ Riddl::Parameter::Complex.new("user_intent","application/json",response.to_json())
227
+ end
228
+ end #}}}
229
+
208
230
  def self::implementation(opts)
209
231
  Proc.new do
210
232
  on resource do
211
- run(CreateMermaid, opts[:llms]) if post 'llm_in'
233
+ run CreateMermaid, opts[:llms] if post 'llm_in'
212
234
 
213
235
  on resource 'dataflow' do
214
- run(CreateDataFlow, opts[:llms]) if post 'dataflow_in'
236
+ run CreateDataFlow, opts[:llms] if post 'dataflow_in'
215
237
  end
216
238
 
217
239
  on resource 'validate' do
218
240
  on resource 'xml' do
219
- run(ValidateDataFlow, opts[:llms]) if post 'dataflow_in'
241
+ run ValidateDataFlow, opts[:llms] if post 'dataflow_in'
220
242
  end
221
243
  end
222
244
 
223
245
  on resource 'text' do
224
246
  on resource 'llm' do
225
- run(CreateText, opts[:llms]) if post 'text_in'
247
+ run CreateText, opts[:llms] if post 'text_in'
226
248
  end
227
249
  end
228
250
 
251
+ on resource 'intent' do
252
+ run GuessIntent, opts[:llms], opts[:plugins] if post 'intent_in'
253
+ end
254
+
229
255
  on resource 'generic' do
230
- run(CreateGeneric, opts[:llms]) if post 'generic_in'
256
+ run CreateGeneric, opts[:llms] if post 'generic_in'
231
257
  end
232
258
  end
233
259
  end
@@ -2,16 +2,17 @@
2
2
  This file is part of CPEE-LLM.
3
3
 
4
4
  CPEE-LLM is free software: you can redistribute it and/or modify it under the
5
- terms of the GNU General Public License as published by the Free Software
6
- Foundation, either version 3 of the License, or (at your option) any later
7
- version.
5
+ terms of the GNU General Public License as published by the Free
6
+ Software Foundation, either version 3 of the License, or (at your option) any
7
+ later version.
8
8
 
9
9
  CPEE-LLM is distributed in the hope that it will be useful, but WITHOUT ANY
10
10
  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
11
+ A PARTICULAR PURPOSE. See the GNU General Public License for more
12
+ details.
12
13
 
13
- You should have received a copy of the GNU General Public License along with
14
- CPEE-LLM (file LICENSE in the main directory). If not, see
14
+ You should have received a copy of the GNU General Public License
15
+ along with CPEE-LLM (file LICENSE in the main directory). If not, see
15
16
  <http://www.gnu.org/licenses/>.
16
17
  -->
17
18
 
@@ -35,9 +36,35 @@
35
36
  <parameter name="rpst_xml" mimetype="application/json"/>
36
37
  </message>
37
38
 
39
+ <message name="intent_in">
40
+ <parameter name="user_input" mimetype="text/plain"/>
41
+ <parameter name="llm" mimetype="text/plain"/>
42
+ </message>
43
+
44
+ <message name="intent_out">
45
+ <parameter name="user_intent" mimetype="application/json"/>
46
+ <!--
47
+ prompt/user/intent.txt
48
+ prompt/system/intent.txt
49
+
50
+ output: json
51
+ {
52
+ url: // url to call
53
+ required_input: {
54
+ text: // typically extracted from user_input
55
+ documents: { name: value, }, // documents to pass
56
+ model: true|false,
57
+ message_id: '' // input is then the message
58
+ }
59
+ output_template: ... // the output text when calling url is written into this template where the %%% is. If the output of calling url is a json, insert multiple %%%name.
60
+ output: 'chat|process|reintent' // write to chat, give to the normal pipeline, or pass the output to the intention service again
61
+ }
62
+ -->
63
+ </message>
64
+
38
65
  <message name="text_in">
39
66
  <parameter name="rpst_xml" mimetype="*/xml"/>
40
- <parameter name="llm" type="string"/>
67
+ <parameter name="llm" mimetype="text/plain"/>
41
68
  </message>
42
69
  <message name="text_out">
43
70
  <parameter name="output_text" mimetype="application/json"/>
@@ -51,6 +78,9 @@
51
78
  <optional>
52
79
  <parameter name="temperature" mimetype="text/plain"/>
53
80
  </optional>
81
+ <zeroOrMore>
82
+ <parameter name="document" mimetype="*"/>
83
+ </zeroOrMore>
54
84
  </message>
55
85
  <message name="generic_out">
56
86
  <parameter name="output_text" mimetype="application/json"/>
@@ -68,6 +98,10 @@
68
98
  <post in="dataflow_in" out="llm_out"/>
69
99
  </resource>
70
100
 
101
+ <resource relative="intent">
102
+ <post in="intent_in" out="intent_out"/>
103
+ </resource>
104
+
71
105
  <resource relative="text">
72
106
  <resource relative="llm">
73
107
  <post in="text_in" out="text_out"/>
@@ -0,0 +1,12 @@
1
+ You are an expert in BPMN modeling, specifically in Mermaid.js format.
2
+ Your task is to validate and transform BPMN models based on user-provided modifications, ensuring compliance with BPMN rules and Mermaid.js syntax.
3
+ You are allowed to adjust only those parts of the process model mentioned in the user-provided modification. Other parts of the model have to stay unchanged.
4
+
5
+ %%%fragments/mermaid/syntax.txt
6
+
7
+ The provided process model may contain nodes whose ids are not integers (e.g., a1, g0s) and nodes of type script (e.g., a3:script:(Compute Total)). Keep these ids and types unchanged. Only new nodes get new unique integer ids.
8
+
9
+ All gateways must have both a split and a merge point.
10
+ Each gateway that initiates a split must be properly closed by a merge gateway of the same type (e.g., an exclusive gateway must be merged by another exclusive gateway).
11
+
12
+ Return only mermaid.js as text without any additional information! Give me just the raw Mermaid.js code without markdown formatting.
@@ -0,0 +1,50 @@
1
+ You are an expert BPMN 2.0 process model editor for the CPEE XML process description language.
2
+ Your task is to modify an existing CPEE XML process model according to the user's natural-language modification request.
3
+ The user will always provide:
4
+ * an existing valid CPEE XML process model;
5
+ * one or more textual modification requests;
6
+
7
+ Core Objective
8
+ Your task is to produce a modified CPEE XML process model that implements the requested changes.
9
+ Only modify the parts of the process that are explicitly or necessarily affected by the user's request.
10
+ Do not redesign, simplify, optimize, refactor, or rewrite unrelated parts of the model.
11
+ Never remove existing functionality unless explicitly requested.
12
+ Never introduce additional behavior that was not requested.
13
+
14
+ Editing Workflow
15
+ Internally perform the following steps:
16
+ 1. Parse the existing CPEE XML description.
17
+ 2. Parse the workflow contained in the description element.
18
+ 3. Understand the user's requested modifications.
19
+ 4. Determine which workflow elements are affected.
20
+ 5. Apply only the requested changes.
21
+ 6. Update documentation flow if necessary.
22
+ 7. Generate the complete updated CPEE XML description.
23
+
24
+ %%%fragments/cpee_xml.txt
25
+ %%%fragments/cpee_xml/documentation.txt
26
+
27
+ For the purpose of modelling, arguments can be ignored and don't have to carry any values. Code also can be left empty. If an argument is given a value that refers to process data, it must use the !data.some_value syntax described above.
28
+
29
+ # Handling Ambiguity
30
+ If the user's request is sufficiently precise, perform the modification directly.
31
+ If multiple valid interpretations exist and the missing information affects the resulting workflow, select the best possible interpretation and perform changes.
32
+
33
+ # Important
34
+ If user deletes a single task in a branch, remove task but leave the branch. Use default branch.
35
+ eid attributes are IDs. All eid attributes have to be unique for the whole XML and start with an e followed by a number, e.g., "e1".
36
+ id attributes are IDs. All id attributes have to be unique for the whole XML and start with an a followed by a number, e.g., "a1".
37
+ Don't change ANY existing id's or eid's. Only generate new unique id's or eid's for new nodes which have id's or eid's.
38
+ Don't change existing nodes, even when you move them. For example don't add documentation if it is not there.
39
+
40
+ # Output Requirements
41
+ Return the complete updated CPEE XML process model.
42
+ Preserve the overall document structure.
43
+ Modify only the elements affected by the user's request.
44
+ Return the entire XML document, including unchanged sections.
45
+ Do not explain the modifications.
46
+ Do not summarize the changes.
47
+ Do not output Markdown.
48
+ Do not omit unchanged sections.
49
+ The returned XML must be immediately usable as a valid CPEE process model.
50
+