|
321f2f5…
|
leo
|
1 |
"""Prompt templates for LLM-based content analysis.""" |
|
829e24a…
|
leo
|
2 |
|
|
321f2f5…
|
leo
|
3 |
import logging |
|
321f2f5…
|
leo
|
4 |
from pathlib import Path |
|
321f2f5…
|
leo
|
5 |
from string import Template |
|
829e24a…
|
leo
|
6 |
from typing import Dict, Optional, Union |
|
321f2f5…
|
leo
|
7 |
|
|
321f2f5…
|
leo
|
8 |
logger = logging.getLogger(__name__) |
|
829e24a…
|
leo
|
9 |
|
|
321f2f5…
|
leo
|
10 |
|
|
321f2f5…
|
leo
|
11 |
class PromptTemplate: |
|
321f2f5…
|
leo
|
12 |
"""Template manager for LLM prompts.""" |
|
829e24a…
|
leo
|
13 |
|
|
321f2f5…
|
leo
|
14 |
def __init__( |
|
829e24a…
|
leo
|
15 |
self, |
|
321f2f5…
|
leo
|
16 |
templates_dir: Optional[Union[str, Path]] = None, |
|
829e24a…
|
leo
|
17 |
default_templates: Optional[Dict[str, str]] = None, |
|
321f2f5…
|
leo
|
18 |
): |
|
321f2f5…
|
leo
|
19 |
""" |
|
321f2f5…
|
leo
|
20 |
Initialize prompt template manager. |
|
829e24a…
|
leo
|
21 |
|
|
321f2f5…
|
leo
|
22 |
Parameters |
|
321f2f5…
|
leo
|
23 |
---------- |
|
321f2f5…
|
leo
|
24 |
templates_dir : str or Path, optional |
|
321f2f5…
|
leo
|
25 |
Directory containing template files |
|
321f2f5…
|
leo
|
26 |
default_templates : dict, optional |
|
321f2f5…
|
leo
|
27 |
Default templates to use |
|
321f2f5…
|
leo
|
28 |
""" |
|
321f2f5…
|
leo
|
29 |
self.templates_dir = Path(templates_dir) if templates_dir else None |
|
321f2f5…
|
leo
|
30 |
self.templates = {} |
|
829e24a…
|
leo
|
31 |
|
|
321f2f5…
|
leo
|
32 |
# Load default templates |
|
321f2f5…
|
leo
|
33 |
if default_templates: |
|
321f2f5…
|
leo
|
34 |
self.templates.update(default_templates) |
|
829e24a…
|
leo
|
35 |
|
|
321f2f5…
|
leo
|
36 |
# Load templates from directory if provided |
|
321f2f5…
|
leo
|
37 |
if self.templates_dir and self.templates_dir.exists(): |
|
321f2f5…
|
leo
|
38 |
self._load_templates_from_dir() |
|
829e24a…
|
leo
|
39 |
|
|
321f2f5…
|
leo
|
40 |
def _load_templates_from_dir(self) -> None: |
|
321f2f5…
|
leo
|
41 |
"""Load templates from template directory.""" |
|
321f2f5…
|
leo
|
42 |
if not self.templates_dir: |
|
321f2f5…
|
leo
|
43 |
return |
|
829e24a…
|
leo
|
44 |
|
|
321f2f5…
|
leo
|
45 |
for template_file in self.templates_dir.glob("*.txt"): |
|
321f2f5…
|
leo
|
46 |
template_name = template_file.stem |
|
321f2f5…
|
leo
|
47 |
try: |
|
321f2f5…
|
leo
|
48 |
with open(template_file, "r", encoding="utf-8") as f: |
|
321f2f5…
|
leo
|
49 |
template_content = f.read() |
|
321f2f5…
|
leo
|
50 |
self.templates[template_name] = template_content |
|
321f2f5…
|
leo
|
51 |
logger.debug(f"Loaded template: {template_name}") |
|
321f2f5…
|
leo
|
52 |
except Exception as e: |
|
321f2f5…
|
leo
|
53 |
logger.warning(f"Error loading template {template_name}: {str(e)}") |
|
829e24a…
|
leo
|
54 |
|
|
321f2f5…
|
leo
|
55 |
def get_template(self, template_name: str) -> Optional[Template]: |
|
321f2f5…
|
leo
|
56 |
""" |
|
321f2f5…
|
leo
|
57 |
Get template by name. |
|
829e24a…
|
leo
|
58 |
|
|
321f2f5…
|
leo
|
59 |
Parameters |
|
321f2f5…
|
leo
|
60 |
---------- |
|
321f2f5…
|
leo
|
61 |
template_name : str |
|
321f2f5…
|
leo
|
62 |
Template name |
|
829e24a…
|
leo
|
63 |
|
|
321f2f5…
|
leo
|
64 |
Returns |
|
321f2f5…
|
leo
|
65 |
------- |
|
321f2f5…
|
leo
|
66 |
Template or None |
|
321f2f5…
|
leo
|
67 |
Template object if found, None otherwise |
|
321f2f5…
|
leo
|
68 |
""" |
|
321f2f5…
|
leo
|
69 |
if template_name not in self.templates: |
|
321f2f5…
|
leo
|
70 |
logger.warning(f"Template not found: {template_name}") |
|
321f2f5…
|
leo
|
71 |
return None |
|
829e24a…
|
leo
|
72 |
|
|
321f2f5…
|
leo
|
73 |
return Template(self.templates[template_name]) |
|
829e24a…
|
leo
|
74 |
|
|
321f2f5…
|
leo
|
75 |
def format_prompt(self, template_name: str, **kwargs) -> Optional[str]: |
|
321f2f5…
|
leo
|
76 |
""" |
|
321f2f5…
|
leo
|
77 |
Format prompt with provided parameters. |
|
829e24a…
|
leo
|
78 |
|
|
321f2f5…
|
leo
|
79 |
Parameters |
|
321f2f5…
|
leo
|
80 |
---------- |
|
321f2f5…
|
leo
|
81 |
template_name : str |
|
321f2f5…
|
leo
|
82 |
Template name |
|
321f2f5…
|
leo
|
83 |
**kwargs : dict |
|
321f2f5…
|
leo
|
84 |
Template parameters |
|
829e24a…
|
leo
|
85 |
|
|
321f2f5…
|
leo
|
86 |
Returns |
|
321f2f5…
|
leo
|
87 |
------- |
|
321f2f5…
|
leo
|
88 |
str or None |
|
321f2f5…
|
leo
|
89 |
Formatted prompt if template exists, None otherwise |
|
321f2f5…
|
leo
|
90 |
""" |
|
321f2f5…
|
leo
|
91 |
template = self.get_template(template_name) |
|
321f2f5…
|
leo
|
92 |
if not template: |
|
321f2f5…
|
leo
|
93 |
return None |
|
829e24a…
|
leo
|
94 |
|
|
321f2f5…
|
leo
|
95 |
try: |
|
321f2f5…
|
leo
|
96 |
return template.safe_substitute(**kwargs) |
|
321f2f5…
|
leo
|
97 |
except Exception as e: |
|
321f2f5…
|
leo
|
98 |
logger.error(f"Error formatting template {template_name}: {str(e)}") |
|
321f2f5…
|
leo
|
99 |
return None |
|
829e24a…
|
leo
|
100 |
|
|
321f2f5…
|
leo
|
101 |
def add_template(self, template_name: str, template_content: str) -> None: |
|
321f2f5…
|
leo
|
102 |
""" |
|
321f2f5…
|
leo
|
103 |
Add or update template. |
|
829e24a…
|
leo
|
104 |
|
|
321f2f5…
|
leo
|
105 |
Parameters |
|
321f2f5…
|
leo
|
106 |
---------- |
|
321f2f5…
|
leo
|
107 |
template_name : str |
|
321f2f5…
|
leo
|
108 |
Template name |
|
321f2f5…
|
leo
|
109 |
template_content : str |
|
321f2f5…
|
leo
|
110 |
Template content |
|
321f2f5…
|
leo
|
111 |
""" |
|
321f2f5…
|
leo
|
112 |
self.templates[template_name] = template_content |
|
829e24a…
|
leo
|
113 |
|
|
321f2f5…
|
leo
|
114 |
def save_template(self, template_name: str) -> bool: |
|
321f2f5…
|
leo
|
115 |
""" |
|
321f2f5…
|
leo
|
116 |
Save template to file. |
|
829e24a…
|
leo
|
117 |
|
|
321f2f5…
|
leo
|
118 |
Parameters |
|
321f2f5…
|
leo
|
119 |
---------- |
|
321f2f5…
|
leo
|
120 |
template_name : str |
|
321f2f5…
|
leo
|
121 |
Template name |
|
829e24a…
|
leo
|
122 |
|
|
321f2f5…
|
leo
|
123 |
Returns |
|
321f2f5…
|
leo
|
124 |
------- |
|
321f2f5…
|
leo
|
125 |
bool |
|
321f2f5…
|
leo
|
126 |
True if successful, False otherwise |
|
321f2f5…
|
leo
|
127 |
""" |
|
321f2f5…
|
leo
|
128 |
if not self.templates_dir: |
|
321f2f5…
|
leo
|
129 |
logger.error("Templates directory not set") |
|
321f2f5…
|
leo
|
130 |
return False |
|
829e24a…
|
leo
|
131 |
|
|
321f2f5…
|
leo
|
132 |
if template_name not in self.templates: |
|
321f2f5…
|
leo
|
133 |
logger.warning(f"Template not found: {template_name}") |
|
321f2f5…
|
leo
|
134 |
return False |
|
829e24a…
|
leo
|
135 |
|
|
321f2f5…
|
leo
|
136 |
try: |
|
321f2f5…
|
leo
|
137 |
self.templates_dir.mkdir(parents=True, exist_ok=True) |
|
321f2f5…
|
leo
|
138 |
template_path = self.templates_dir / f"{template_name}.txt" |
|
829e24a…
|
leo
|
139 |
|
|
321f2f5…
|
leo
|
140 |
with open(template_path, "w", encoding="utf-8") as f: |
|
321f2f5…
|
leo
|
141 |
f.write(self.templates[template_name]) |
|
829e24a…
|
leo
|
142 |
|
|
321f2f5…
|
leo
|
143 |
logger.debug(f"Saved template: {template_name}") |
|
321f2f5…
|
leo
|
144 |
return True |
|
321f2f5…
|
leo
|
145 |
except Exception as e: |
|
321f2f5…
|
leo
|
146 |
logger.error(f"Error saving template {template_name}: {str(e)}") |
|
321f2f5…
|
leo
|
147 |
return False |
|
829e24a…
|
leo
|
148 |
|
|
321f2f5…
|
leo
|
149 |
|
|
321f2f5…
|
leo
|
150 |
# Default prompt templates |
|
321f2f5…
|
leo
|
151 |
DEFAULT_TEMPLATES = { |
|
321f2f5…
|
leo
|
152 |
"content_analysis": """ |
|
321f2f5…
|
leo
|
153 |
Analyze the provided video content and extract key information: |
|
321f2f5…
|
leo
|
154 |
|
|
321f2f5…
|
leo
|
155 |
TRANSCRIPT: |
|
321f2f5…
|
leo
|
156 |
$transcript |
|
321f2f5…
|
leo
|
157 |
|
|
321f2f5…
|
leo
|
158 |
VISUAL ELEMENTS (if available): |
|
321f2f5…
|
leo
|
159 |
$visual_elements |
|
321f2f5…
|
leo
|
160 |
|
|
321f2f5…
|
leo
|
161 |
Please extract and organize the following: |
|
321f2f5…
|
leo
|
162 |
- Main topics and themes |
|
321f2f5…
|
leo
|
163 |
- Key points for each topic |
|
321f2f5…
|
leo
|
164 |
- Important details or facts |
|
321f2f5…
|
leo
|
165 |
- Action items or follow-ups |
|
321f2f5…
|
leo
|
166 |
- Relationships between concepts |
|
829e24a…
|
leo
|
167 |
|
|
321f2f5…
|
leo
|
168 |
Format the output as structured markdown. |
|
321f2f5…
|
leo
|
169 |
""", |
|
321f2f5…
|
leo
|
170 |
"diagram_extraction": """ |
|
829e24a…
|
leo
|
171 |
Analyze the following image that contains a diagram, whiteboard content, |
|
829e24a…
|
leo
|
172 |
or other visual information. |
|
829e24a…
|
leo
|
173 |
|
|
321f2f5…
|
leo
|
174 |
Extract and convert this visual information into a structured representation. |
|
829e24a…
|
leo
|
175 |
|
|
321f2f5…
|
leo
|
176 |
If it's a flowchart, process diagram, or similar structured visual: |
|
321f2f5…
|
leo
|
177 |
- Identify the components and their relationships |
|
321f2f5…
|
leo
|
178 |
- Preserve the logical flow and structure |
|
321f2f5…
|
leo
|
179 |
- Convert it to mermaid diagram syntax |
|
829e24a…
|
leo
|
180 |
|
|
321f2f5…
|
leo
|
181 |
If it's a whiteboard with text, bullet points, or unstructured content: |
|
321f2f5…
|
leo
|
182 |
- Extract all text elements |
|
321f2f5…
|
leo
|
183 |
- Preserve hierarchical organization if present |
|
321f2f5…
|
leo
|
184 |
- Maintain any emphasized or highlighted elements |
|
829e24a…
|
leo
|
185 |
|
|
321f2f5…
|
leo
|
186 |
Image context: $image_context |
|
829e24a…
|
leo
|
187 |
|
|
321f2f5…
|
leo
|
188 |
Return the results as markdown with appropriate structure. |
|
321f2f5…
|
leo
|
189 |
""", |
|
321f2f5…
|
leo
|
190 |
"action_item_detection": """ |
|
321f2f5…
|
leo
|
191 |
Review the following transcript and identify all action items, commitments, or follow-up tasks. |
|
829e24a…
|
leo
|
192 |
|
|
321f2f5…
|
leo
|
193 |
TRANSCRIPT: |
|
321f2f5…
|
leo
|
194 |
$transcript |
|
829e24a…
|
leo
|
195 |
|
|
321f2f5…
|
leo
|
196 |
For each action item, extract: |
|
321f2f5…
|
leo
|
197 |
- The specific action to be taken |
|
321f2f5…
|
leo
|
198 |
- Who is responsible (if mentioned) |
|
321f2f5…
|
leo
|
199 |
- Any deadlines or timeframes |
|
321f2f5…
|
leo
|
200 |
- Priority level (if indicated) |
|
321f2f5…
|
leo
|
201 |
- Context or additional details |
|
829e24a…
|
leo
|
202 |
|
|
321f2f5…
|
leo
|
203 |
Format the results as a structured list of action items. |
|
321f2f5…
|
leo
|
204 |
""", |
|
321f2f5…
|
leo
|
205 |
"content_summary": """ |
|
321f2f5…
|
leo
|
206 |
Provide a concise summary of the following content: |
|
321f2f5…
|
leo
|
207 |
|
|
321f2f5…
|
leo
|
208 |
$content |
|
321f2f5…
|
leo
|
209 |
|
|
321f2f5…
|
leo
|
210 |
The summary should: |
|
321f2f5…
|
leo
|
211 |
- Capture the main points and key takeaways |
|
321f2f5…
|
leo
|
212 |
- Be approximately 3-5 paragraphs |
|
321f2f5…
|
leo
|
213 |
- Focus on the most important information |
|
321f2f5…
|
leo
|
214 |
- Maintain a neutral, objective tone |
|
321f2f5…
|
leo
|
215 |
|
|
321f2f5…
|
leo
|
216 |
Format the summary as clear, readable text. |
|
321f2f5…
|
leo
|
217 |
""", |
|
321f2f5…
|
leo
|
218 |
"summary_generation": """ |
|
321f2f5…
|
leo
|
219 |
Generate a comprehensive summary of the following transcript content. |
|
321f2f5…
|
leo
|
220 |
|
|
321f2f5…
|
leo
|
221 |
CONTENT: |
|
321f2f5…
|
leo
|
222 |
$content |
|
321f2f5…
|
leo
|
223 |
|
|
321f2f5…
|
leo
|
224 |
Provide a well-structured summary that: |
|
321f2f5…
|
leo
|
225 |
- Captures the main topics discussed |
|
321f2f5…
|
leo
|
226 |
- Highlights key decisions or conclusions |
|
321f2f5…
|
leo
|
227 |
- Notes any important context or background |
|
321f2f5…
|
leo
|
228 |
- Is 3-5 paragraphs long |
|
321f2f5…
|
leo
|
229 |
|
|
321f2f5…
|
leo
|
230 |
Write in clear, professional prose. |
|
321f2f5…
|
leo
|
231 |
""", |
|
321f2f5…
|
leo
|
232 |
"key_points_extraction": """ |
|
321f2f5…
|
leo
|
233 |
Extract the key points from the following content. |
|
321f2f5…
|
leo
|
234 |
|
|
321f2f5…
|
leo
|
235 |
CONTENT: |
|
321f2f5…
|
leo
|
236 |
$content |
|
321f2f5…
|
leo
|
237 |
|
|
321f2f5…
|
leo
|
238 |
Return a JSON array of key point objects. Each object should have: |
|
321f2f5…
|
leo
|
239 |
- "point": the key point (1-2 sentences) |
|
321f2f5…
|
leo
|
240 |
- "topic": category or topic area (optional) |
|
321f2f5…
|
leo
|
241 |
- "details": supporting details (optional) |
|
321f2f5…
|
leo
|
242 |
|
|
321f2f5…
|
leo
|
243 |
Example format: |
|
321f2f5…
|
leo
|
244 |
[ |
|
829e24a…
|
leo
|
245 |
{"point": "The system uses microservices architecture", |
|
829e24a…
|
leo
|
246 |
"topic": "Architecture", "details": "Each service handles a specific domain"}, |
|
321f2f5…
|
leo
|
247 |
] |
|
321f2f5…
|
leo
|
248 |
|
|
321f2f5…
|
leo
|
249 |
Return ONLY the JSON array, no additional text. |
|
321f2f5…
|
leo
|
250 |
""", |
|
321f2f5…
|
leo
|
251 |
"entity_extraction": """ |
|
829e24a…
|
leo
|
252 |
Extract all notable entities (people, concepts, technologies, organizations, |
|
829e24a…
|
leo
|
253 |
time references) from the following content. |
|
321f2f5…
|
leo
|
254 |
CONTENT: |
|
321f2f5…
|
leo
|
255 |
$content |
|
321f2f5…
|
leo
|
256 |
|
|
321f2f5…
|
leo
|
257 |
Return a JSON array of entity objects: |
|
321f2f5…
|
leo
|
258 |
[ |
|
829e24a…
|
leo
|
259 |
{"name": "entity name", |
|
829e24a…
|
leo
|
260 |
"type": "person|concept|technology|organization|time", |
|
829e24a…
|
leo
|
261 |
"description": "brief description"} |
|
321f2f5…
|
leo
|
262 |
|
|
321f2f5…
|
leo
|
263 |
Return ONLY the JSON array, no additional text. |
|
321f2f5…
|
leo
|
264 |
""", |
|
321f2f5…
|
leo
|
265 |
"relationship_extraction": """ |
|
321f2f5…
|
leo
|
266 |
Given the following content and entities, identify relationships between them. |
|
321f2f5…
|
leo
|
267 |
|
|
321f2f5…
|
leo
|
268 |
CONTENT: |
|
321f2f5…
|
leo
|
269 |
$content |
|
321f2f5…
|
leo
|
270 |
|
|
321f2f5…
|
leo
|
271 |
KNOWN ENTITIES: |
|
321f2f5…
|
leo
|
272 |
$entities |
|
321f2f5…
|
leo
|
273 |
|
|
321f2f5…
|
leo
|
274 |
Return a JSON array of relationship objects: |
|
321f2f5…
|
leo
|
275 |
[ |
|
829e24a…
|
leo
|
276 |
{"source": "entity A", "target": "entity B", |
|
829e24a…
|
leo
|
277 |
"type": "relationship type (e.g., uses, manages, depends_on, created_by, part_of)"} |
|
321f2f5…
|
leo
|
278 |
|
|
321f2f5…
|
leo
|
279 |
Return ONLY the JSON array, no additional text. |
|
321f2f5…
|
leo
|
280 |
""", |
|
321f2f5…
|
leo
|
281 |
"diagram_analysis": """ |
|
321f2f5…
|
leo
|
282 |
Analyze the following text extracted from a diagram or visual element. |
|
321f2f5…
|
leo
|
283 |
|
|
321f2f5…
|
leo
|
284 |
DIAGRAM TEXT: |
|
321f2f5…
|
leo
|
285 |
$diagram_text |
|
321f2f5…
|
leo
|
286 |
|
|
321f2f5…
|
leo
|
287 |
Identify: |
|
321f2f5…
|
leo
|
288 |
1. The type of diagram (flowchart, architecture, sequence, etc.) |
|
321f2f5…
|
leo
|
289 |
2. The main components and their roles |
|
321f2f5…
|
leo
|
290 |
3. The relationships between components |
|
321f2f5…
|
leo
|
291 |
4. Any data flows or process steps |
|
321f2f5…
|
leo
|
292 |
|
|
321f2f5…
|
leo
|
293 |
Return a JSON object: |
|
321f2f5…
|
leo
|
294 |
{ |
|
321f2f5…
|
leo
|
295 |
"diagram_type": "type", |
|
321f2f5…
|
leo
|
296 |
"components": ["list of components"], |
|
321f2f5…
|
leo
|
297 |
"relationships": ["component A -> component B: description"], |
|
321f2f5…
|
leo
|
298 |
"summary": "brief description of what the diagram shows" |
|
321f2f5…
|
leo
|
299 |
} |
|
321f2f5…
|
leo
|
300 |
|
|
321f2f5…
|
leo
|
301 |
Return ONLY the JSON object, no additional text. |
|
321f2f5…
|
leo
|
302 |
""", |
|
321f2f5…
|
leo
|
303 |
"mermaid_generation": """ |
|
321f2f5…
|
leo
|
304 |
Convert the following diagram information into valid Mermaid diagram syntax. |
|
321f2f5…
|
leo
|
305 |
|
|
321f2f5…
|
leo
|
306 |
Diagram Type: $diagram_type |
|
321f2f5…
|
leo
|
307 |
Text Content: $text_content |
|
321f2f5…
|
leo
|
308 |
Analysis: $semantic_analysis |
|
321f2f5…
|
leo
|
309 |
|
|
321f2f5…
|
leo
|
310 |
Generate a Mermaid diagram that accurately represents the visual structure. |
|
321f2f5…
|
leo
|
311 |
Use the appropriate Mermaid diagram type (graph, sequenceDiagram, classDiagram, etc.). |
|
321f2f5…
|
leo
|
312 |
|
|
321f2f5…
|
leo
|
313 |
Return ONLY the Mermaid code, no markdown fences or explanations. |
|
829e24a…
|
leo
|
314 |
""", |
|
321f2f5…
|
leo
|
315 |
} |
|
321f2f5…
|
leo
|
316 |
|
|
321f2f5…
|
leo
|
317 |
# Create default prompt template manager |
|
321f2f5…
|
leo
|
318 |
default_prompt_manager = PromptTemplate(default_templates=DEFAULT_TEMPLATES) |