yasserrmd commited on
Commit
26063ff
1 Parent(s): c23e423

Upload 4 files

Browse files
Files changed (4) hide show
  1. .env +1 -0
  2. app.py +156 -0
  3. index.html +173 -0
  4. requirements.txt +8 -0
.env ADDED
@@ -0,0 +1 @@
 
 
1
+ GROQ_API_KEY="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"
app.py ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, File, UploadFile
2
+ from fastapi.responses import FileResponse
3
+ from groq import Groq
4
+ import os
5
+ import base64
6
+ from io import BytesIO
7
+ from PIL import Image
8
+ from mdextractor import extract_md_blocks
9
+ from pydantic import BaseModel
10
+ from processpiper.text2diagram import render
11
+ from dotenv import load_dotenv
12
+
13
+ load_dotenv()
14
+
15
+ app = FastAPI()
16
+
17
+ PIPERFLOW_SYNTAX_DOC=""" Generate BPMN diagram using English like PiperFlow syntax
18
+ To create a process map using PirperFlow, you need to define the diagram using a specific syntax. Here is an example:
19
+
20
+
21
+
22
+
23
+ title: Sample Test Process
24
+ colourtheme: GREENTURTLE
25
+ lane: End User
26
+ (start) as start
27
+ [Enter Keyword] as enter_keyword
28
+ (end) as end
29
+ pool: System Search
30
+ lane: Database System
31
+ [Login] as login
32
+ [Search Records] as search_records
33
+ <Result Found?> as result_found
34
+ [Display Result] as display_result
35
+ [Logout] as logout
36
+ lane: Log System
37
+ [Log Error] as log_error
38
+
39
+ start->login->enter_keyword->search_records->result_found->display_result->logout->end
40
+ result_found->log_error->display_result
41
+
42
+ footer: Generated by ProcessPiper
43
+
44
+
45
+
46
+ Import the render function from processpiper.text2diagram
47
+ Call the render function with the input syntax and the output file name.
48
+ Syntax
49
+ Diagram Configurations
50
+ The PiperFlow syntax for defining a process map is as follows:
51
+
52
+ title: The title of the diagram.
53
+ footer: The footer text to display on the diagram.
54
+ width : (Optional) Specify the width of the diagram.
55
+ colourtheme: The colour theme to use
56
+ Lane & Pool Configurations
57
+ lane: The name of the lane.
58
+ pool: The name of the pool.
59
+ Element/Shape Configurations
60
+ To add elements to the lane, use one of the following tags. You place your element description within the tag:
61
+ Use ( and ) to create event element
62
+ use (start) to create a start event
63
+ use (end) to create an end event
64
+ use (@timer and ) to create a timer event. Example (@timer Trigger every 1 hour) as timer_event
65
+ use (@intermediate and ) to create an intermediate event. Example (@intermediate Message Received) as intermediate_event
66
+ use (@message and ) to create a message event
67
+ use (@signal and ) to create a signal event
68
+ use (@conditional and ) to create a conditional event
69
+ use (@link and ) to create a link event
70
+ Use [ and ] to create an activity. By default, the activity type is TASK. Example [Place Order] as place_order
71
+ use [@subprocess] to create a subprocess. Example `[@subprocess Get Approval] as get_approval``
72
+ Use < and > to create a gateway. By default, the gateway type is EXCLUSIVE. Example <Result Found?> as result_found
73
+ Use <@parallel and > to create a parallel gateway. Example <@parallel Span Out> as span_out
74
+ Use <@inclusive and > to create an inclusive gateway. Example <@inclusive Condition Met?> as condition_met
75
+ Use <@event and > to create an event gateway
76
+ Connection Configurations
77
+ To connect two elements, use ->. You can chain multiple connections using ->:
78
+ Example:
79
+ login->enter_keyword
80
+ start->login->enter_keyword->search_records->result_found->display_result->logout->end
81
+ To add label to the connection, add ":" when connecting elements. ❗ NOTE: This is a breaking change in v0.6. Versions prior to 0.6 use start-"Enter Credentials->login syntax. See this page for more information.
82
+ Example:
83
+ start->login: Enter credentials
84
+ To specify the connection point manually, add connection side. See How to select sides for more information.
85
+ Example:
86
+ start-(bottom, top)->login
87
+ start-(bottom, top)->login: Enter credentials
88
+ Indentation is not required. However, it is recommended to use indentation to make the diagram easier to read.
89
+
90
+ currently available color themes are
91
+ Default
92
+ GREYWOOF
93
+ BLUEMOUNTAIN
94
+ ORANGEPEEL
95
+ GREENTURTLE
96
+ SUNFLOWER
97
+ PURPLERAIN
98
+ RUBYRED
99
+ TEALWATERS
100
+ SEAFOAMS
101
+
102
+ """
103
+
104
+
105
+
106
+
107
+ GROQ_API_KEY = os.getenv("GROQ_API_KEY")
108
+
109
+ class Prompt(BaseModel):
110
+ prompt: str
111
+
112
+ def generate_diagram(input_syntax):
113
+ _, generated_image = render(input_syntax)
114
+ # Convert the image to a base64 encoded string
115
+ buffered = BytesIO()
116
+ generated_image.save(buffered, format="PNG")
117
+ img_str = base64.b64encode(buffered.getvalue())
118
+ return img_str.decode("utf-8")
119
+
120
+ @app.get("/")
121
+ def read_root():
122
+ return FileResponse("index.html")
123
+
124
+ @app.post("/generate/")
125
+ async def generate_bpmn(prompt:Prompt):
126
+ client = Groq(api_key=GROQ_API_KEY)
127
+
128
+
129
+ completion = client.chat.completions.create(
130
+ model="llama3-70b-8192",
131
+ messages=[
132
+ {
133
+ "role": "system",
134
+ "content": "you are business process flow generator using the following piperflow text\n\n" + PIPERFLOW_SYNTAX_DOC
135
+ },
136
+ {
137
+ "role": "user",
138
+ "content": "generate the piperflow text for the below scenario\n\n" + prompt.prompt
139
+ }
140
+ ],
141
+ temperature=1,
142
+ max_tokens=1024,
143
+ top_p=1,
144
+ stream=False,
145
+ stop=None,
146
+ )
147
+
148
+ print(completion.choices[0].message.content or "", end="")
149
+
150
+ piperFlowText=extract_md_blocks(completion.choices[0].message.content)[0]
151
+ print(piperFlowText)
152
+
153
+ return {"pipeFlowImage":generate_diagram(piperFlowText),"pipeFlowText":piperFlowText}
154
+ if __name__ == "__main__":
155
+ import uvicorn
156
+ uvicorn.run(app, host="0.0.0.0", port=8000)
index.html ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ <!DOCTYPE html>
3
+ <html lang="en">
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>BPMN Diagram Generator</title>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.1.3/css/bootstrap.min.css">
9
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css">
10
+ <style>
11
+ body {
12
+ background-color: #f8f9fa;
13
+ }
14
+
15
+ .card {
16
+ background-color: #fff;
17
+ border-radius: 12px;
18
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
19
+ }
20
+
21
+ .card-header {
22
+ background-color: #343a40;
23
+ color: #fff;
24
+ border-top-left-radius: 12px;
25
+ border-top-right-radius: 12px;
26
+ }
27
+
28
+ .btn-primary {
29
+ background-color: #007bff;
30
+ border-color: #007bff;
31
+ }
32
+
33
+ .btn-primary:hover {
34
+ background-color: #0056b3;
35
+ border-color: #004a99;
36
+ }
37
+
38
+ .btn-secondary {
39
+ background-color: #6c757d;
40
+ border-color: #6c757d;
41
+ }
42
+
43
+ .btn-secondary:hover {
44
+ background-color: #5a6268;
45
+ border-color: #545b62;
46
+ }
47
+
48
+ .loader {
49
+ border: 4px solid #f3f3f3;
50
+ border-top: 4px solid #007bff;
51
+ border-radius: 50%;
52
+ width: 30px;
53
+ height: 30px;
54
+ animation: spin 2s linear infinite;
55
+ }
56
+
57
+ @keyframes spin {
58
+ 0% { transform: rotate(0deg); }
59
+ 100% { transform: rotate(360deg); }
60
+ }
61
+ </style>
62
+ </head>
63
+ <body>
64
+ <div class="container my-5">
65
+ <h1 class="mb-4 text-center text-dark">
66
+ <i class="fas fa-project-diagram mr-2"></i>
67
+ BPMN Generator
68
+ </h1>
69
+ <div class="row justify-content-center">
70
+ <div class="col-md-12">
71
+ <div class="card mb-4">
72
+ <div class="card-header">
73
+ <i class="fas fa-code mr-2"></i>
74
+ Generate BPMN
75
+ </div>
76
+ <div class="card-body">
77
+ <div class="form-group">
78
+ <label for="promptInput" class="form-label">Enter text:</label>
79
+ <textarea class="form-control" id="promptInput" rows="3"></textarea>
80
+ </div>
81
+ <div class="form-group" style="margin-top: 20px;">
82
+ <div class="d-flex justify-content-between">
83
+ <button class="btn btn-primary" id="generateButton">
84
+ <i class="fa fa-cog fa-spin d-none" id="loadingIcon"></i>
85
+ Generate
86
+ </button>
87
+ <button class="btn btn-secondary" id="saveButton" style="display: none;">
88
+ <i class="fas fa-download mr-2"></i>
89
+ Save Image
90
+ </button>
91
+ </div>
92
+ </div>
93
+ </div>
94
+ </div>
95
+ <div class="card">
96
+ <div class="card-header">
97
+ <i class="fas fa-file-alt mr-2"></i>
98
+ Output
99
+ </div>
100
+ <div class="card-body">
101
+ <div class="form-group" style="display: none;">
102
+ <label for="pipeFlowText" class="form-label">Pipe Flow Text:</label>
103
+ <p id="pipeFlowText"></p>
104
+ </div>
105
+ <div class="form-group">
106
+ <label for="pipeFlowImage" class="form-label">Pipe Flow Image:</label>
107
+ <img id="pipeFlowImage" alt="Pipe Flow Image" class="img-fluid d-none">
108
+ </div>
109
+ </div>
110
+ </div>
111
+ </div>
112
+ </div>
113
+ </div>
114
+
115
+ <script>
116
+ const generateButton = document.getElementById('generateButton');
117
+ const saveButton = document.getElementById('saveButton');
118
+ const loadingIcon = document.getElementById('loadingIcon');
119
+ const pipeFlowText = document.getElementById('pipeFlowText');
120
+ const pipeFlowImage = document.getElementById('pipeFlowImage');
121
+
122
+
123
+ generateButton.addEventListener('click', async () => {
124
+ const promptInput = document.getElementById('promptInput').value;
125
+ if (!promptInput) {
126
+ alert('Please enter some text.');
127
+ return;
128
+ }
129
+
130
+ // Show the loading indicator
131
+ loadingIcon.classList.remove('d-none');
132
+
133
+ try {
134
+ const response = await fetch('http://localhost:8000/generate/', {
135
+ method: 'POST',
136
+ headers: {
137
+ 'Content-Type': 'application/json'
138
+ },
139
+ body: JSON.stringify({ prompt: promptInput })
140
+ });
141
+
142
+ const data = await response.json();
143
+
144
+ // Hide the loading indicator
145
+ loadingIcon.classList.add('d-none');
146
+
147
+ pipeFlowText.textContent = data.pipeFlowText;
148
+
149
+ if (data.pipeFlowImage) {
150
+ pipeFlowImage.src = `data:image/png;base64,${data.pipeFlowImage}`;
151
+ pipeFlowImage.classList.remove('d-none');
152
+ saveButton.style.display = 'inline-block';
153
+ } else {
154
+ pipeFlowImage.classList.add('d-none');
155
+ saveButton.style.display = 'none';
156
+ }
157
+
158
+ saveButton.addEventListener('click', () => {
159
+ const link = document.createElement('a');
160
+ link.download = 'bpmn-diagram.png';
161
+ link.href = pipeFlowImage.src;
162
+ link.click();
163
+ });
164
+ } catch (error) {
165
+ // Hide the loading indicator
166
+ loadingIcon.classList.add('d-none');
167
+ alert('Error generating the BPMN diagram. Please try again later.');
168
+ console.error('Error:', error);
169
+ }
170
+ });
171
+ </script>
172
+ </body>
173
+ </html>
requirements.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ fastapi
2
+ python-multipart
3
+ fastapi-cors
4
+ groq
5
+ python-dotenv
6
+ unicorn
7
+ processpiper
8
+ mdextractor