cpee-llm 1.0.5 → 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 +2 -2
- data/lib/cpee/llm/functions.rb +96 -67
- data/lib/cpee/llm/implementation.rb +42 -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.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 -107
- 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 +29 -15
- /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
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 173032c1cbbc6ff2fa8ecb64b3ad47dc3c8998e9f978cb3ba137228948c1ad93
|
|
4
|
+
data.tar.gz: '090933e62d1ceb692f42762c6c7c2efa06f4c842032e2d38ac202cbd77eb7150'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ff11667abbf905c538f416b28642c6d91edab16f1e4c77e2344f31f9770e240c52c900d8a7f9bf29af57df40a3f3946aae33b1cc3e548edf093921a175cd0c69
|
|
7
|
+
data.tar.gz: cfeeacc7885181012472be6be35677ea66521bc10e6141812b212a1e2390a01bcd9f10e86d752de8f83b0e2972dc5896be50d9e936d50df2aa4dd1e27ab68cc6
|
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,6 +1,6 @@
|
|
|
1
1
|
Gem::Specification.new do |s|
|
|
2
2
|
s.name = "cpee-llm"
|
|
3
|
-
s.version = "1.0
|
|
3
|
+
s.version = "1.1.0"
|
|
4
4
|
s.platform = Gem::Platform::RUBY
|
|
5
5
|
s.license = "LGPL-3.0-or-later"
|
|
6
6
|
s.summary = "CPEE Conversational Agents"
|
|
@@ -26,5 +26,5 @@ Gem::Specification.new do |s|
|
|
|
26
26
|
s.add_runtime_dependency 'typhoeus', '~> 1.4'
|
|
27
27
|
s.add_runtime_dependency 'ruby_llm', '~> 1.15'
|
|
28
28
|
s.add_runtime_dependency 'rag_embeddings', '~> 0'
|
|
29
|
-
s.add_runtime_dependency 'cpee-transformation', '~> 1
|
|
29
|
+
s.add_runtime_dependency 'cpee-transformation', '~> 1'
|
|
30
30
|
end
|
data/lib/cpee/llm/functions.rb
CHANGED
|
@@ -45,15 +45,9 @@ module CPEE
|
|
|
45
45
|
trans.generate_model(CPEE::Transformation::Target::CPEE)
|
|
46
46
|
end #}}}
|
|
47
47
|
|
|
48
|
-
def
|
|
48
|
+
def error_handler #{{{
|
|
49
49
|
begin
|
|
50
|
-
|
|
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,38 +57,71 @@ 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("generate1.txt")
|
|
63
|
+
user_prompt = build_user_prompt("process_description.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
|
-
|
|
70
|
-
|
|
77
|
+
error_handler do
|
|
78
|
+
system_prompt = build_system_prompt("apply.txt")
|
|
79
|
+
user_prompt = build_user_prompt("process_model_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
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
87
|
+
end
|
|
88
|
+
end #}}}
|
|
89
|
+
|
|
90
|
+
def adapt_doccpee_description(myllm,doc,user_input,llms) #{{{
|
|
91
|
+
input_cpee = doc.to_s()
|
|
92
|
+
error_handler do
|
|
93
|
+
system_prompt = build_system_prompt("adapt_docxml_description.txt")
|
|
94
|
+
user_prompt = build_user_prompt("process_model_adapt.txt", user_input:, process_model: input_cpee)
|
|
95
|
+
llm_response = generate_content(myllm,system_prompt,user_prompt,16000,0,llms)
|
|
96
|
+
# raise exceptions if response is empty for some reason
|
|
97
|
+
if llm_response.nil? || llm_response.empty?
|
|
98
|
+
raise LLMError.new("Something went wrong and your content was not generated!", 500)
|
|
99
|
+
else
|
|
100
|
+
llm_response = llm_response.strip
|
|
101
|
+
inside = llm_response.scan(/```(\w+)?\s*\n(.*?)\n```/m)
|
|
102
|
+
llm_response = inside.empty? ? llm_response : inside[0][1]
|
|
103
|
+
#check if response is xml:
|
|
104
|
+
begin
|
|
105
|
+
XML::Smart.string(llm_response)
|
|
106
|
+
rescue Nokogiri::XML::SyntaxError => e
|
|
107
|
+
raise LLMError.new("Something went wrong and llm was not able to generate valid xml model: #{llm_response}", 500)
|
|
108
|
+
end
|
|
109
|
+
return llm_response
|
|
110
|
+
end
|
|
81
111
|
end
|
|
82
112
|
end #}}}
|
|
83
113
|
|
|
84
114
|
def adapt_cpee_model(myllm,doc,user_input,existing_endpoints,endpoints,llms) #{{{
|
|
85
|
-
testset = XML::Smart.string(
|
|
86
|
-
<testset xmlns="http://cpee.org/ns/properties/2.0">
|
|
87
|
-
</testset>
|
|
88
|
-
XML
|
|
115
|
+
testset = XML::Smart.string('<testset xmlns="http://cpee.org/ns/properties/2.0"></testset>')
|
|
89
116
|
root = testset.root
|
|
90
117
|
root.add(existing_endpoints.root)
|
|
91
118
|
dslx = root.add("dslx")
|
|
92
119
|
dslx.add(doc.root)
|
|
93
120
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
llm_response =
|
|
121
|
+
error_handler do
|
|
122
|
+
system_prompt = build_system_prompt("adapt_xml_endpoints.txt")
|
|
123
|
+
user_prompt = build_user_prompt("process_model_adapt_api.txt", user_input:, process_model: testset, api_specification: endpoints)
|
|
124
|
+
llm_response = generate_content(myllm,system_prompt,user_prompt,15000,0,llms)
|
|
98
125
|
# raise exceptions if response is empty for some reason
|
|
99
126
|
if llm_response.nil? || llm_response.empty?
|
|
100
127
|
raise LLMError.new("Something went wrong and your content was not generated!", 500)
|
|
@@ -110,54 +137,42 @@ module CPEE
|
|
|
110
137
|
end
|
|
111
138
|
return llm_response
|
|
112
139
|
end
|
|
113
|
-
rescue LLMError => e_llm
|
|
114
|
-
raise e_llm
|
|
115
|
-
rescue Exception => e
|
|
116
|
-
raise e
|
|
117
140
|
end
|
|
118
141
|
end #}}}
|
|
119
142
|
|
|
120
143
|
def generate_text(myllm,doc,llms) #{{{
|
|
121
144
|
input_cpee = doc.to_s()
|
|
122
145
|
input_mermaid = cpee_to_mermaid(doc.to_s())
|
|
123
|
-
|
|
124
|
-
|
|
146
|
+
error_handler do
|
|
147
|
+
system_prompt = build_system_prompt("describe.txt")
|
|
148
|
+
user_prompt = build_user_prompt("process_model_text.txt", user_input: input_mermaid)
|
|
149
|
+
llm_response = generate_content(myllm,system_prompt,user_prompt,4000,0,llms)
|
|
125
150
|
# raise exceptions if response is empty for some reason
|
|
126
151
|
if llm_response.nil? || llm_response.empty?
|
|
127
152
|
raise LLMError.new("Something went wrong and your content was not generated!", 500)
|
|
128
153
|
else
|
|
129
154
|
return llm_response
|
|
130
155
|
end
|
|
131
|
-
rescue LLMError => e_llm
|
|
132
|
-
e_llm.message
|
|
133
|
-
raise e_llm
|
|
134
|
-
rescue Exception => e
|
|
135
|
-
e.message
|
|
136
|
-
raise e
|
|
137
156
|
end
|
|
138
157
|
end #}}}
|
|
139
158
|
|
|
140
|
-
def generate_generic(myllm,user_input,system_prompt,format,temperature,llms) #{{{
|
|
141
|
-
|
|
142
|
-
llm_response =
|
|
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)
|
|
143
162
|
# raise exceptions if response is empty for some reason
|
|
144
163
|
if llm_response.nil? || llm_response.empty?
|
|
145
164
|
raise LLMError.new("Something went wrong and your content was not generated!", 500)
|
|
146
165
|
else
|
|
147
166
|
return llm_response
|
|
148
167
|
end
|
|
149
|
-
rescue LLMError => e_llm
|
|
150
|
-
e_llm.message
|
|
151
|
-
raise e_llm
|
|
152
|
-
rescue Exception => e
|
|
153
|
-
e.message
|
|
154
|
-
raise e
|
|
155
168
|
end
|
|
156
169
|
end #}}}
|
|
157
170
|
|
|
158
171
|
def generate_dataflow(myllm,mermaid_model,api_specification,llms) #{{{
|
|
159
|
-
|
|
160
|
-
|
|
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)
|
|
161
176
|
# raise exceptions if response is empty for some reason
|
|
162
177
|
if llm_response.nil? || llm_response.empty?
|
|
163
178
|
raise LLMError.new("Something went wrong and your content was not generated!", 500)
|
|
@@ -175,36 +190,28 @@ module CPEE
|
|
|
175
190
|
end
|
|
176
191
|
return llm_response
|
|
177
192
|
end
|
|
178
|
-
rescue LLMError => e_llm
|
|
179
|
-
e_llm.message
|
|
180
|
-
raise e_llm
|
|
181
|
-
rescue Exception => e
|
|
182
|
-
e.message
|
|
183
|
-
raise e
|
|
184
193
|
end
|
|
185
194
|
end #}}}
|
|
186
195
|
|
|
187
196
|
def generate_endpoint_model(myllm,user_input,endpoints,llms) #{{{
|
|
188
|
-
|
|
189
|
-
|
|
197
|
+
error_handler do
|
|
198
|
+
system_prompt = build_system_prompt("generate_enpoints.txt")
|
|
199
|
+
user_prompt = build_user_prompt("process_description_endpoints.txt", user_input:, endpoints:)
|
|
200
|
+
llm_response = generate_content(myllm,system_prompt,user_prompt,4000,0.1,llms)
|
|
190
201
|
# raise exceptions if response is empty for some reason
|
|
191
202
|
if llm_response.nil? || llm_response.empty?
|
|
192
203
|
raise LLMError.new("Something went wrong and your content was not generated!", 500)
|
|
193
204
|
else
|
|
194
205
|
return llm_response
|
|
195
206
|
end
|
|
196
|
-
rescue LLMError => e_llm
|
|
197
|
-
e_llm.message
|
|
198
|
-
raise e_llm
|
|
199
|
-
rescue Exception => e
|
|
200
|
-
e.message
|
|
201
|
-
raise e
|
|
202
207
|
end
|
|
203
208
|
end #}}}
|
|
204
209
|
|
|
205
210
|
def validate_cpee_model(myllm,cpee_model,llms) #{{{
|
|
206
|
-
|
|
207
|
-
|
|
211
|
+
error_handler do
|
|
212
|
+
system_prompt = build_system_prompt("validate_xml.txt")
|
|
213
|
+
user_prompt = build_user_prompt("cpee_repair.txt", cpee_model:)
|
|
214
|
+
llm_response = generate_content(myllm,system_prompt,user_prompt,0,0.1,llms)
|
|
208
215
|
if llm_response.nil? || llm_response.empty?
|
|
209
216
|
raise LLMError.new("Something went wrong and your content was not generated!", 500)
|
|
210
217
|
elsif llm_response.strip.downcase == "perfect"
|
|
@@ -221,12 +228,34 @@ module CPEE
|
|
|
221
228
|
end
|
|
222
229
|
return llm_response
|
|
223
230
|
end
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
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
|
|
230
259
|
end
|
|
231
260
|
end #}}}
|
|
232
261
|
|
|
@@ -42,7 +42,7 @@ module CPEE
|
|
|
42
42
|
|
|
43
43
|
doc = XML::Smart.string(input_cpee)
|
|
44
44
|
begin
|
|
45
|
-
output_cpee = if prompt_type == 'generate_noendpoints'
|
|
45
|
+
output_cpee = if prompt_type == 'generate_noendpoints' || prompt_type == 'generate_noendpoints_docdescription'
|
|
46
46
|
llm_response = generate_model(myllm,user_input,temperature,llms)
|
|
47
47
|
mermaid_to_cpee(llm_response)
|
|
48
48
|
elsif prompt_type == 'generate_endpoints'
|
|
@@ -52,6 +52,8 @@ module CPEE
|
|
|
52
52
|
elsif prompt_type == 'adapt_noendpoints'
|
|
53
53
|
llm_response = adapt_model(myllm,doc,user_input,llms)
|
|
54
54
|
mermaid_to_cpee(llm_response)
|
|
55
|
+
elsif prompt_type == 'adapt_noendpoints_docdescription'
|
|
56
|
+
adapt_doccpee_description(myllm,doc,user_input,llms)
|
|
55
57
|
elsif prompt_type == 'adapt_endpoints'
|
|
56
58
|
xml_endpoints = XML::Smart.string(endpoints)
|
|
57
59
|
adapt_cpee_model(myllm,doc,user_input,xml_endpoints,get_demo_endpoints(),llms)
|
|
@@ -61,7 +63,7 @@ module CPEE
|
|
|
61
63
|
return Riddl::Parameter::Complex.new('llm_out', 'application/json', { error: e }.to_json)
|
|
62
64
|
end
|
|
63
65
|
|
|
64
|
-
return
|
|
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())
|
|
65
67
|
rescue LLMError => e
|
|
66
68
|
@status = e&.http_response || 400
|
|
67
69
|
return Riddl::Parameter::Complex.new("llm_out","application/json",{ :error => "#{prompt_type} #{e.message}"}.to_json())
|
|
@@ -112,18 +114,20 @@ module CPEE
|
|
|
112
114
|
llms = @a[0]
|
|
113
115
|
#get parameters
|
|
114
116
|
begin
|
|
115
|
-
myllm
|
|
116
|
-
user_input
|
|
117
|
-
system_prompt = @p
|
|
118
|
-
format
|
|
119
|
-
temperature
|
|
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'
|
|
120
124
|
rescue Exception => e
|
|
121
125
|
@status = 400
|
|
122
126
|
return Riddl::Parameter::Complex.new("generic_out","application/json",{:error => e}.to_json())
|
|
123
127
|
end
|
|
124
128
|
|
|
125
129
|
begin
|
|
126
|
-
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)
|
|
127
131
|
rescue LLMError => e
|
|
128
132
|
@status = e.http_response
|
|
129
133
|
return Riddl::Parameter::Complex.new("generic_out","application/json",{:error => e.message}.to_json())
|
|
@@ -202,29 +206,54 @@ module CPEE
|
|
|
202
206
|
end
|
|
203
207
|
end #}}}
|
|
204
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
|
+
|
|
205
230
|
def self::implementation(opts)
|
|
206
231
|
Proc.new do
|
|
207
232
|
on resource do
|
|
208
|
-
run
|
|
233
|
+
run CreateMermaid, opts[:llms] if post 'llm_in'
|
|
209
234
|
|
|
210
235
|
on resource 'dataflow' do
|
|
211
|
-
run
|
|
236
|
+
run CreateDataFlow, opts[:llms] if post 'dataflow_in'
|
|
212
237
|
end
|
|
213
238
|
|
|
214
239
|
on resource 'validate' do
|
|
215
240
|
on resource 'xml' do
|
|
216
|
-
run
|
|
241
|
+
run ValidateDataFlow, opts[:llms] if post 'dataflow_in'
|
|
217
242
|
end
|
|
218
243
|
end
|
|
219
244
|
|
|
220
245
|
on resource 'text' do
|
|
221
246
|
on resource 'llm' do
|
|
222
|
-
run
|
|
247
|
+
run CreateText, opts[:llms] if post 'text_in'
|
|
223
248
|
end
|
|
224
249
|
end
|
|
225
250
|
|
|
251
|
+
on resource 'intent' do
|
|
252
|
+
run GuessIntent, opts[:llms], opts[:plugins] if post 'intent_in'
|
|
253
|
+
end
|
|
254
|
+
|
|
226
255
|
on resource 'generic' do
|
|
227
|
-
run
|
|
256
|
+
run CreateGeneric, opts[:llms] if post 'generic_in'
|
|
228
257
|
end
|
|
229
258
|
end
|
|
230
259
|
end
|
|
@@ -35,9 +35,35 @@
|
|
|
35
35
|
<parameter name="rpst_xml" mimetype="application/json"/>
|
|
36
36
|
</message>
|
|
37
37
|
|
|
38
|
+
<message name="intent_in">
|
|
39
|
+
<parameter name="user_input" mimetype="text/plain"/>
|
|
40
|
+
<parameter name="llm" mimetype="text/plain"/>
|
|
41
|
+
</message>
|
|
42
|
+
|
|
43
|
+
<message name="intent_out">
|
|
44
|
+
<parameter name="user_intent" mimetype="application/json"/>
|
|
45
|
+
<!--
|
|
46
|
+
prompt/user/intent.txt
|
|
47
|
+
prompt/system/intent.txt
|
|
48
|
+
|
|
49
|
+
output: json
|
|
50
|
+
{
|
|
51
|
+
url: // url to call
|
|
52
|
+
required_input: {
|
|
53
|
+
text: // typically extracted from user_input
|
|
54
|
+
documents: { name: value, }, // documents to pass
|
|
55
|
+
model: true|false,
|
|
56
|
+
message_id: '' // input is then the message
|
|
57
|
+
}
|
|
58
|
+
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.
|
|
59
|
+
output: 'chat|process|reintent' // write to chat, give to the normal pipeline, or pass the output to the intention service again
|
|
60
|
+
}
|
|
61
|
+
-->
|
|
62
|
+
</message>
|
|
63
|
+
|
|
38
64
|
<message name="text_in">
|
|
39
65
|
<parameter name="rpst_xml" mimetype="*/xml"/>
|
|
40
|
-
<parameter name="llm"
|
|
66
|
+
<parameter name="llm" mimetype="text/plain"/>
|
|
41
67
|
</message>
|
|
42
68
|
<message name="text_out">
|
|
43
69
|
<parameter name="output_text" mimetype="application/json"/>
|
|
@@ -51,6 +77,9 @@
|
|
|
51
77
|
<optional>
|
|
52
78
|
<parameter name="temperature" mimetype="text/plain"/>
|
|
53
79
|
</optional>
|
|
80
|
+
<zeroOrMore>
|
|
81
|
+
<parameter name="document" mimetype="*"/>
|
|
82
|
+
</zeroOrMore>
|
|
54
83
|
</message>
|
|
55
84
|
<message name="generic_out">
|
|
56
85
|
<parameter name="output_text" mimetype="application/json"/>
|
|
@@ -68,6 +97,10 @@
|
|
|
68
97
|
<post in="dataflow_in" out="llm_out"/>
|
|
69
98
|
</resource>
|
|
70
99
|
|
|
100
|
+
<resource relative="intent">
|
|
101
|
+
<post in="intent_in" out="intent_out"/>
|
|
102
|
+
</resource>
|
|
103
|
+
|
|
71
104
|
<resource relative="text">
|
|
72
105
|
<resource relative="llm">
|
|
73
106
|
<post in="text_in" out="text_out"/>
|
|
@@ -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
|
+
3. Parse the workflow contained in the description element.
|
|
18
|
+
4. Understand the user's requested modifications.
|
|
19
|
+
5. Determine which workflow elements are affected.
|
|
20
|
+
6. Apply only the requested changes.
|
|
21
|
+
7. Update documentation flow if necessary.
|
|
22
|
+
8. Generate the complete updated CPEE XML description.
|
|
23
|
+
|
|
24
|
+
%%%cpee_xml.txt
|
|
25
|
+
%%%cpee_xml_documentation_modelling.txt
|
|
26
|
+
|
|
27
|
+
For the purpose of modelling, arguments can be ignored and dont have to cary anny values. Code also can be left empty.
|
|
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 genereate 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 dont 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
|
+
|
|
@@ -64,81 +64,7 @@ If the task does not exist in the Service Registry:
|
|
|
64
64
|
- Leave the task unconfigured except for information explicitly requested by the user.
|
|
65
65
|
Always use the Service Registry whenever a matching service specification is available.
|
|
66
66
|
|
|
67
|
-
|
|
68
|
-
The process model itself is contained entirely inside the <description> element. Interpret the XML inside <description> using the following mapping.
|
|
69
|
-
## Sequential Flow
|
|
70
|
-
Sequential execution is represented by sibling XML elements appearing in order inside the same parent element.
|
|
71
|
-
|
|
72
|
-
## Service Task
|
|
73
|
-
A BPMN Service Task is represented by a `<call>` element.
|
|
74
|
-
The endpoint of the service is stored in the **endpoint attribute**.
|
|
75
|
-
<call endpoint="measurelightingconditions">
|
|
76
|
-
The following child elements may appear inside `<call>`:
|
|
77
|
-
├── parameters
|
|
78
|
-
│ ├── label
|
|
79
|
-
│ ├── method
|
|
80
|
-
│ └── arguments
|
|
81
|
-
├── code
|
|
82
|
-
│ ├── signal
|
|
83
|
-
│ ├── prepare
|
|
84
|
-
│ ├── finalize
|
|
85
|
-
│ ├── update
|
|
86
|
-
│ └── rescue
|
|
87
|
-
├── annotations
|
|
88
|
-
└── documentation
|
|
89
|
-
|
|
90
|
-
The <method> field must strictly follow the Service Registry specification.
|
|
91
|
-
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>).
|
|
92
|
-
Never invent, infer, or assume a method value that is not explicitly defined in the service specification:
|
|
93
|
-
<method/>
|
|
94
|
-
|
|
95
|
-
Service input parameters are stored inside arguments. Each argument is represented by its own child element.
|
|
96
|
-
<arguments>
|
|
97
|
-
<min>1</min>
|
|
98
|
-
<max>100</max>
|
|
99
|
-
</arguments>
|
|
100
|
-
If an argument depends on a previously computed or returned value, it must be provided using the !data.some_value syntax.
|
|
101
|
-
<arguments>
|
|
102
|
-
<step>!data.current_step</step>
|
|
103
|
-
</arguments>
|
|
104
|
-
|
|
105
|
-
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.
|
|
106
|
-
<finalize output="result"> data.temperature = result["temperature"].to_f; data.type = result["celsius"];</finalize>
|
|
107
|
-
|
|
108
|
-
## Script Task
|
|
109
|
-
A BPMN Script Task is represented by <manipulate>. The executable Ruby code is stored inside the <code> child element:
|
|
110
|
-
<manipulate><code>data.counter += 1</code></manipulate>
|
|
111
|
-
|
|
112
|
-
## Exclusive Gateway
|
|
113
|
-
An Exclusive Gateway is represented by <choose>
|
|
114
|
-
Each outgoing branch is represented by <alternative> child.
|
|
115
|
-
The branch condition is stored in the **condition attribute**.
|
|
116
|
-
<alternative condition="data.temperature > 30">
|
|
117
|
-
Conditions must be valid Ruby expressions.
|
|
118
|
-
|
|
119
|
-
## Loop
|
|
120
|
-
A BPMN loop is represented by <loop>
|
|
121
|
-
The loop condition is stored in the **condition attribute**. The loop execution mode is stored in the **mode attribute** (pre_test/post_test)
|
|
122
|
-
<loop mode="pre_test" condition="data.counter < 10">
|
|
123
|
-
Loop conditions must be valid Ruby expressions.
|
|
124
|
-
|
|
125
|
-
## Parallel Gateway
|
|
126
|
-
Parallel execution is represented by <parallel>
|
|
127
|
-
Each concurrent branch is represented by <parallel_branch>
|
|
128
|
-
|
|
129
|
-
##Pause Task
|
|
130
|
-
A pause is represented by a <stop> element.
|
|
131
|
-
A <stop> pauses the execution of the process (until it is manually resumed). It does not terminate the process.
|
|
132
|
-
<stop id="a5"/>
|
|
133
|
-
When the user requests to pause, hold, or stop the process, insert a <stop> element.
|
|
134
|
-
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.
|
|
135
|
-
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.
|
|
136
|
-
|
|
137
|
-
## Variables
|
|
138
|
-
Variables are referenced as: data.variable_name
|
|
139
|
-
Service outputs are returned as strings unless otherwise specified.
|
|
140
|
-
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:
|
|
141
|
-
data.temperature = result["temperature"].to_f
|
|
67
|
+
%%%cpee_xml.txt
|
|
142
68
|
|
|
143
69
|
# Handling Ambiguity
|
|
144
70
|
If the user's request is sufficiently precise, perform the modification directly.
|
|
@@ -154,4 +80,3 @@ If multiple valid interpretations exist and the missing information affects the
|
|
|
154
80
|
Do not output Markdown.
|
|
155
81
|
Do not omit unchanged sections.
|
|
156
82
|
The returned XML must be immediately usable as a valid CPEE process model.
|
|
157
|
-
|