Adam-Ben-Khalifa commited on
Commit
a35e572
·
verified ·
1 Parent(s): d62810a

added pipeline.py

Browse files
Files changed (1) hide show
  1. pipeline.py +242 -0
pipeline.py ADDED
@@ -0,0 +1,242 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Importing dependecies
2
+ import os
3
+ import asyncio
4
+ from openai import AsyncOpenAI
5
+ from dotenv import load_dotenv
6
+
7
+
8
+ # Setting up the API key for single project
9
+ # 1/ create a .env file and add to it:
10
+ # OPENAI_API_KEY = the_personal_api_key
11
+ # 2/ load variables from .env file
12
+ load_dotenv()
13
+ # 3/ set up the client
14
+ client = AsyncOpenAI(
15
+ api_key=os.getenv("OPENAI_API_KEY"),
16
+ )
17
+
18
+
19
+ # Defining the PromptEnhancer class containing the necessary components for the Advanced Prompt Generation Pipeline
20
+ class PromptEnhancer:
21
+ def __init__(self, model="gpt-4o-mini", tools_dict={}):
22
+ self.model = model
23
+ self.prompt_tokens = 0
24
+ self.completion_tokens = 0
25
+ self.tools_dict = tools_dict
26
+
27
+ async def call_llm(self, prompt):
28
+ """Call the LLM with the given prompt"""
29
+ response = await client.chat.completions.create(
30
+ model=self.model,
31
+ messages=[
32
+ {"role": "system",
33
+ "content": "You are an assistant designed to provide concise and specific information based solely on the given tasks.\
34
+ Do not include any additional information, explanations, or context beyond what is explicitly requested."
35
+ },
36
+ {"role": "user",
37
+ "content": prompt
38
+ }
39
+ ],
40
+ temperature=0.0, # from 0 (precise and almost deterministic answer) to 2 (creative and almost random answer)
41
+ )
42
+ # counting the I/O tokens
43
+ self.prompt_tokens += response.usage.prompt_tokens
44
+ self.completion_tokens += response.usage.completion_tokens
45
+
46
+ return response.choices[0].message.content
47
+
48
+ async def analyze_input(self, basic_prompt):
49
+ """Analyze the input prompt to determine its key information"""
50
+ analysis_prompt = f"""
51
+ Analyze the following {{prompt}} and generate brief answers to these key information that will be beneficial to enhance the prompt:
52
+ 1. Main topic of the prompt
53
+ 2. The most convenient output format for the prompt
54
+ 3. Specific requirements for the prompt, if necessary
55
+ 4. Suggested strategies to enhance the prompt for better output result
56
+
57
+ {{prompt}}: {basic_prompt}
58
+
59
+ Your output will be only the result of the information required above in text format.
60
+ Do not return a general explanation of the generation process.
61
+ """
62
+ return await self.call_llm(analysis_prompt)
63
+
64
+ async def expand_instructions(self, basic_prompt, analysis):
65
+ """Expand the basic prompt with clear, detailed instructions"""
66
+ expansion_prompt = f"""
67
+ Based on this {{analysis}}:
68
+
69
+ {analysis}
70
+
71
+ Expand the following {{basic_prompt}} following these instructions:
72
+ 1. Add relevant details to clarify the prompt only if necessary
73
+ 2. Suggest an appropriate persona for the AI Model
74
+ 3. Generate 1-2 related examples to guide the output generation
75
+ 4. Suggest an optimal output length
76
+ 5. Use delimiter, {{ }}, to clearly indicate the parts of the input that should be concidered as variables
77
+
78
+ {{basic_prompt}}: {basic_prompt}
79
+
80
+ Your output will be only the result of the information required above in text format and not a dictionary format.
81
+ Make sure the generated output maintains the sructure of a prompt for an AI Model.
82
+ Make sure the generated output maintains the goal and context of the {{basic_prompt}}.
83
+ Do not include the instructions headers in the generated answer.
84
+ Do not return a general explanation of the generation process.
85
+ Do not generate an answer for the prompt.
86
+ """
87
+ return await self.call_llm(expansion_prompt)
88
+
89
+ async def decompose_task(self, expanded_prompt):
90
+ """Break down complex tasks into subtasks"""
91
+ decomposition_prompt = f"""
92
+ Break down the following {{prompt}} into subtasks for better output generation and follow these instructions:
93
+ 1. Identify main task components and their corresponding subtasks
94
+ 2. Create specific instructions for each subtask
95
+ 3. Define success criteria for each subtask
96
+
97
+ {{prompt}}: {expanded_prompt}
98
+
99
+ Your output will be only the result of the task required above in text format.
100
+ Follow the (Main-task/ Sub-task/ Instructions/ Success-criteria) format.
101
+ Do not return a general explanation of the generation process.
102
+ """
103
+ return await self.call_llm(decomposition_prompt)
104
+
105
+ async def add_reasoning(self, expanded_prompt):
106
+ """Add instructions for showing reasoning, chain-of-thought, and self-review"""
107
+ reasoning_prompt = f"""
108
+ Based on the following {{prompt}}, suggest instructions in order to guide the AI Model to:
109
+ 1. Show reasoning through using the chain-of-thought process
110
+ 2. Use inner-monologue only if it is recommended to hide parts of the thought process
111
+ 3. Self-review and check for missed information
112
+
113
+ {{prompt}}: {expanded_prompt}
114
+
115
+ Your output will be only the set of instructions in text format.
116
+ Do not return a general explanation of the generation process.
117
+ """
118
+ return await self.call_llm(reasoning_prompt)
119
+
120
+ async def create_eval_criteria(self, expanded_prompt):
121
+ """Generate evaluation criteria for the prompt output"""
122
+ evaluation_prompt = f"""
123
+ Create evaluation criteria for assessing the quality of the output for this {{prompt}}:
124
+ 1. List 1-3 specific criteria
125
+ 2. Briefly explain how to measure each criterion
126
+
127
+ {{prompt}}: {expanded_prompt}
128
+
129
+ Your output will be only the result of the information required above in text format.
130
+ Do not return a general explanation of the generation process.
131
+ """
132
+ return await self.call_llm(evaluation_prompt)
133
+
134
+ async def suggest_references(self, expanded_prompt):
135
+ """Suggest relevant references and explain how to use them"""
136
+ reference_prompt = f"""
137
+ For the following {{prompt}}, suggest relevant reference texts or sources that could help enhance the output of the prompt if possible,
138
+ and if not, do not return anything:
139
+ 1. List 0-3 potential references
140
+ 2. Briefly explain how to incorporate these references to enhance the prompt
141
+
142
+ {{prompt}}: {expanded_prompt}
143
+
144
+ Your output will be only the result of the information required above in a dictionary called "References" containing the references titles as keys,
145
+ and their corresponding explanation of incorporation as values. If no references will be suggested, return an empty dictionary.
146
+ Do not return a general explanation of the generation process.
147
+ """
148
+ return await self.call_llm(reference_prompt)
149
+
150
+ async def suggest_tools(self, expanded_prompt, tools_dict):
151
+ """Suggest relevant external tools or APIs"""
152
+ tool_prompt = f"""
153
+ For the following {{prompt}}, suggest relevant external tools from the provided {{tools_dict}} that can enhance the prompt for better execution.
154
+ If the prompt does not require tools for its output, it is highly-recommended to not return any tools:
155
+ 1. List 0-3 potential tools/APIs
156
+ 2. Briefly explain how to use these tools within the prompt
157
+
158
+ {{prompt}}: {expanded_prompt}
159
+ {{tools_dict}}: {tools_dict}
160
+
161
+ Your output will be only the result of the information required above in a dictionary containing the suggested tools as keys,
162
+ and their corresponding way of usage with the prompt as values. If no tools will be suggested, return an empty dictionary.
163
+ Do not return a general explanation of the generation process.
164
+ """
165
+ return await self.call_llm(tool_prompt)
166
+
167
+ async def assemble_prompt(self, components):
168
+ """Assemble all components into a cohesive advanced prompt"""
169
+ assembly_prompt = f"""
170
+ Assemble all the following {{components}} into a cohesive, and well-structured advanced prompt and do not generate a response for the prompt.
171
+ Make sure to combine the {{reasoning_process}} and {{subtasks}} sections into one section called {{reasoning_process_and_subtasks}}.
172
+
173
+ {{components}}: {components}
174
+
175
+ Your output will be only the result of the tasks required above,
176
+ which is an advanced coherent prompt generated from the combination of the given components dictionary.
177
+ Keep only the {{reasoning_process_and_subtasks}} section instead of the {{reasoning_process}} and {{subtasks}} sections in the output.
178
+ Ensure that the assembled prompt maintains the delimiter structure of variables and the suggested persona.
179
+ Make sure that each sub-section of the prompt is clear and has a title.
180
+ The output is in plain text format and not a dictionary format.
181
+ Do not return a general explanation of the generation process.
182
+ Take the return-to-line symbol into consideration.
183
+ Remove the "**Expanded Prompt**" header.
184
+ """
185
+ return await self.call_llm(assembly_prompt)
186
+
187
+ async def auto_eval(self, assembled_prompt, evaluation_criteria):
188
+ """Perform Auto-Evaluation and Auto-Adjustment"""
189
+ auto_eval_prompt = f"""
190
+ Perform any minor adjustments on the given {{prompt}} based on how likely its output will satisfy these {{evaluation_criteria}}.
191
+ Only perform minor changes if it is necessary and return the updated prompt as output.
192
+ If no changes are necessary, do not change the prompt and return it as output.
193
+
194
+ {{prompt}}: {assembled_prompt}
195
+ {{evaluation_criteria}}: {evaluation_criteria}
196
+
197
+ Your output will be only the result of the tasks required above, which is an updated version of the {{prompt}}, in text format.
198
+ Make sure to keep the {{evaluation_criteria}} in the output prompt.
199
+ Do not return a general explanation of the generation process.
200
+ Make sure there is no generated answer for the prompt.
201
+ Make sure to maintain the stucture of the {{prompt}}.
202
+ """
203
+ return await self.call_llm(auto_eval_prompt)
204
+
205
+ async def enhance_prompt(self, basic_prompt, perform_eval=False):
206
+ """Main method to enhance a basic prompt to an advanced one"""
207
+ analysis = await self.analyze_input(basic_prompt)
208
+ expanded_prompt = await self.expand_instructions(basic_prompt, analysis)
209
+
210
+ evaluation_criteria, references, subtasks, reasoning, tools = await asyncio.gather(
211
+ self.create_eval_criteria(expanded_prompt),
212
+ self.suggest_references(expanded_prompt),
213
+ self.decompose_task(expanded_prompt),
214
+ self.add_reasoning(expanded_prompt),
215
+ self.suggest_tools(expanded_prompt, tools_dict={}),
216
+ )
217
+
218
+ components = {
219
+ "expanded_prompt": expanded_prompt,
220
+ "references": references,
221
+ "subtasks": subtasks,
222
+ "tools": tools,
223
+ "reasoning_process": reasoning,
224
+ "evaluation_criteria": evaluation_criteria,
225
+
226
+ }
227
+
228
+ assembled_prompt = await self.assemble_prompt(components)
229
+
230
+ if perform_eval:
231
+ eveluated_prompt = await self.auto_eval(assembled_prompt, evaluation_criteria)
232
+ advanced_prompt = eveluated_prompt
233
+ else:
234
+ advanced_prompt = assembled_prompt
235
+
236
+ return {
237
+ "advanced_prompt": advanced_prompt,
238
+ "assembled_prompt": assembled_prompt,
239
+ "components": components,
240
+ "analysis": analysis,
241
+ }
242
+