ALLOUNE commited on
Commit
be240c1
·
1 Parent(s): a7372e0

add visual prior art

Browse files
Files changed (3) hide show
  1. app.py +152 -224
  2. src/core.py +3 -3
  3. src/services/processor.py +13 -7
app.py CHANGED
@@ -4,7 +4,10 @@ from typing import Dict, List
4
  import gradio as gr
5
  import pandas as pd
6
  import json
 
7
  from src.core import *
 
 
8
 
9
  app = FastAPI(
10
  title="Insight Finder",
@@ -58,13 +61,13 @@ async def process_constraints(constraints: InputConstraints):
58
 
59
  @app.post("/prior-art-constraints", response_model=OutputPriorArt)
60
  async def prior_art_constraints(data: InputPriorArtConstraints):
61
- prior_art = process_prior_art(data.technologies, data.constraints, "constraints")
62
  print(prior_art)
63
  return prior_art
64
 
65
  @app.post("/prior-art-problems", response_model=OutputPriorArt)
66
  async def prior_art_problems(data: InputPriorArtProblem):
67
- prior_art = process_prior_art(data.technologies, data.problems, "problem")
68
  return prior_art
69
 
70
  def make_json_serializable(data):
@@ -135,7 +138,120 @@ def format_final_technologies_html(technologies_list: list) -> str:
135
  """
136
  html_content += "</div>"
137
  return "<h1>The best technologies combinations </h1>" + html_content
138
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139
  def process_input_gradio(problem_description: str):
140
  """
141
  Processes the input problem description step-by-step for Gradio.
@@ -169,12 +285,6 @@ def process_input_gradio(problem_description: str):
169
 
170
  # Step 8: Get Technologies by ID
171
  best_technologies = get_technologies_by_id(best_technologies_id, global_tech)
172
-
173
- print(constraints)
174
-
175
- print(best_combinations)
176
-
177
- print(best_technologies)
178
 
179
  # Format outputs for Gradio
180
  # For Constraints:
@@ -186,17 +296,20 @@ def process_input_gradio(problem_description: str):
186
  # For Final Technologies:
187
  final_technologies_html = format_final_technologies_html(best_technologies)
188
 
189
- prior_art = process_prior_art(best_technologies, constraints, "constraints")
190
- print(prior_art)
191
-
192
  return (
193
  prompt,
194
  constraints_html, # Output HTML for constraints
195
  best_combinations_html, # Output HTML for best combinations
196
  ", ".join(map(str, best_technologies_id)), # Still a simple text list
197
- final_technologies_html # Output HTML for final technologies
 
 
198
  )
199
 
 
 
 
 
200
 
201
  # --- Gradio Interface Setup ---
202
  input_problem = gr.Textbox(
@@ -209,212 +322,11 @@ output_constraints = gr.HTML(label="2. Retrieved Constraints") # Changed to HTML
209
  output_best_combinations = gr.HTML(label="7. Best Technology Combinations Found") # Changed to HTML
210
  output_selected_ids = gr.Textbox(label="8. Selected Technology IDs", interactive=False)
211
  output_final_technologies = gr.HTML(label="9. Final Best Technologies") # Changed to HTML
 
 
 
 
212
 
213
- # Custom CSS for a professional look and specific output styling
214
- custom_css = """
215
- /* General Body and Font Styling */
216
- body {
217
- font-family: 'Segoe UI', 'Roboto', 'Helvetica Neue', Arial, sans-serif;
218
- color: #333;
219
- background-color: #f0f2f5;
220
- }
221
-
222
- /* Header Styling */
223
- .gradio-container h1 {
224
- color: #0056b3; /* A deep blue for the main title */
225
- text-align: center;
226
- margin-bottom: 10px;
227
- font-weight: 600;
228
- font-size: 2.5em;
229
- text-shadow: 1px 1px 2px rgba(0,0,0,0.1);
230
- }
231
-
232
- .gradio-container h2 {
233
- color: #007bff; /* A slightly lighter blue for subtitles */
234
- text-align: center;
235
- margin-top: 0;
236
- margin-bottom: 30px;
237
- font-weight: 400;
238
- font-size: 1.2em;
239
- }
240
-
241
- /* Card-like styling for individual components */
242
- .gradio-container .gr-box {
243
- background-color: #ffffff;
244
- border-radius: 12px;
245
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
246
- padding: 20px;
247
- margin-bottom: 20px;
248
- border: 1px solid #e0e0e0;
249
- }
250
-
251
- /* Input Textbox Styling */
252
- .gradio-container input[type="text"],
253
- .gradio-container textarea {
254
- border: 1px solid #ced4da;
255
- border-radius: 8px;
256
- padding: 12px 15px;
257
- font-size: 1em;
258
- color: #495057;
259
- transition: border-color 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
260
- }
261
-
262
- .gradio-container input[type="text"]:focus,
263
- .gradio-container textarea:focus {
264
- border-color: #007bff;
265
- box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
266
- outline: none;
267
- }
268
-
269
- /* Button Styling */
270
- .gradio-container button {
271
- background-color: #28a745; /* A vibrant green for action */
272
- color: white;
273
- border: none;
274
- border-radius: 8px;
275
- padding: 12px 25px;
276
- font-size: 1.1em;
277
- font-weight: 500;
278
- cursor: pointer;
279
- transition: background-color 0.2s ease-in-out, transform 0.1s ease-in-out;
280
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
281
- }
282
-
283
- .gradio-container button:hover {
284
- background-color: #218838; /* Darker green on hover */
285
- transform: translateY(-2px);
286
- }
287
-
288
- .gradio-container button:active {
289
- transform: translateY(0);
290
- }
291
-
292
- /* Labels for outputs */
293
- .gradio-container label {
294
- font-weight: 600;
295
- color: #495057;
296
- margin-bottom: 8px;
297
- display: block; /* Ensure labels are on their own line */
298
- font-size: 1.1em;
299
- }
300
-
301
- /* --- Specific Styling for Outputs --- */
302
-
303
- /* 2. Retrieved Constraints Styling */
304
- .constraints-container {
305
- padding: 15px;
306
- background-color: #f8f9fa;
307
- border-radius: 8px;
308
- border: 1px solid #e9ecef;
309
- font-family: 'Trebuchet MS', 'Lucida Grande', 'Lucida Sans Unicode', 'Lucida Sans', Tahoma, sans-serif; /* Different font */
310
- line-height: 1.6;
311
- max-height: 300px;
312
- overflow-y: auto;
313
- }
314
- .constraint-item {
315
- margin-bottom: 10px;
316
- padding-bottom: 10px;
317
- border-bottom: 1px dashed #e0e0e0;
318
- }
319
- .constraint-item:last-child {
320
- border-bottom: none;
321
- margin-bottom: 0;
322
- padding-bottom: 0;
323
- }
324
- .constraint-title {
325
- font-weight: bold;
326
- color: #004085; /* Darker blue for constraint titles */
327
- font-size: 1.1em;
328
- }
329
- .constraint-description {
330
- color: #333;
331
- font-size: 1em;
332
- }
333
-
334
- /* 7. Best Technology Combinations Found & 9. Final Best Technologies Styling */
335
- .combinations-outer-container, .final-tech-container {
336
- padding: 15px;
337
- background-color: #f8f9fa;
338
- border-radius: 8px;
339
- border: 1px solid #e9ecef;
340
- max-height: 500px; /* Adjust as needed */
341
- overflow-y: auto;
342
- font-family: 'Trebuchet MS', 'Lucida Grande', 'Lucida Sans Unicode', 'Lucida Sans', Tahoma, sans-serif; /* Different font */
343
- }
344
-
345
- .problem-card {
346
- background-color: #ffffff;
347
- border: 1px solid #cfe2ff; /* Light blue border for problem card */
348
- border-radius: 10px;
349
- padding: 20px;
350
- margin-bottom: 20px;
351
- box-shadow: 0 4px 10px rgba(0, 0, 0, 0.05);
352
- }
353
- .problem-card-title {
354
- color: #0056b3; /* Deep blue for problem title */
355
- font-size: 1.4em;
356
- margin-top: 0;
357
- margin-bottom: 15px;
358
- border-bottom: 2px solid #cfe2ff;
359
- padding-bottom: 10px;
360
- }
361
-
362
- .technologies-inner-container {
363
- display: grid;
364
- grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); /* Responsive grid for technologies */
365
- gap: 15px;
366
- }
367
-
368
- .technology-card, .final-tech-card {
369
- background-color: #f0faff; /* Very light blue for technology cards */
370
- border: 1px solid #b0d9ff; /* Slightly darker blue border */
371
- border-radius: 8px;
372
- padding: 15px;
373
- box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05);
374
- transition: transform 0.2s ease-in-out;
375
- }
376
-
377
- .technology-card:hover, .final-tech-card:hover {
378
- transform: translateY(-3px);
379
- }
380
-
381
- .tech-card-title, .final-tech-title {
382
- color: #007bff; /* Gradio's primary blue */
383
- font-size: 1.2em;
384
- margin-top: 0;
385
- margin-bottom: 10px;
386
- font-weight: 600;
387
- }
388
-
389
- .technology-card p, .final-tech-card p {
390
- font-size: 0.95em;
391
- line-height: 1.5;
392
- margin-bottom: 5px;
393
- color: #555;
394
- }
395
- .technology-card p strong, .final-tech-card p strong {
396
- color: #004085; /* Darker blue for bold labels */
397
- }
398
-
399
- /* Responsive adjustments */
400
- @media (max-width: 768px) {
401
- .gradio-container {
402
- padding: 15px;
403
- }
404
- .gradio-container h1 {
405
- font-size: 2em;
406
- }
407
- .gradio-container button {
408
- width: 100%;
409
- padding: 15px;
410
- }
411
- .technologies-inner-container {
412
- grid-template-columns: 1fr; /* Stack columns on smaller screens */
413
- }
414
- }
415
- """
416
-
417
- # Create the Gradio Blocks demo with custom theme and CSS
418
  with gr.Blocks(
419
  theme=gr.themes.Soft(),
420
  css=custom_css
@@ -436,12 +348,19 @@ with gr.Blocks(
436
  with gr.Row():
437
  with gr.Column():
438
  output_prompt.render()
439
- output_constraints.render() # Renders HTML
440
  with gr.Column():
441
- output_selected_ids.render() # This remains a Textbox
442
- output_best_combinations.render() # Renders HTML
443
- output_final_technologies.render() # Renders HTML
444
-
 
 
 
 
 
 
 
445
  process_button.click(
446
  fn=process_input_gradio,
447
  inputs=input_problem,
@@ -450,10 +369,19 @@ with gr.Blocks(
450
  output_constraints,
451
  output_best_combinations,
452
  output_selected_ids,
453
- output_final_technologies
 
 
454
  ]
455
  )
456
 
 
 
 
 
 
 
 
457
  gr.mount_gradio_app(app, gradio_app_blocks, path="/gradio")
458
  #if __name__ == "__main__":
459
  # gradio_app_blocks.launch()
 
4
  import gradio as gr
5
  import pandas as pd
6
  import json
7
+ import re
8
  from src.core import *
9
+ from src.ressources.main_css import *
10
+
11
 
12
  app = FastAPI(
13
  title="Insight Finder",
 
61
 
62
  @app.post("/prior-art-constraints", response_model=OutputPriorArt)
63
  async def prior_art_constraints(data: InputPriorArtConstraints):
64
+ prior_art = process_prior_art(data.technologies, data.constraints, "constraints", "pydantic")
65
  print(prior_art)
66
  return prior_art
67
 
68
  @app.post("/prior-art-problems", response_model=OutputPriorArt)
69
  async def prior_art_problems(data: InputPriorArtProblem):
70
+ prior_art = process_prior_art(data.technologies, data.problems, "problem", "pydantic")
71
  return prior_art
72
 
73
  def make_json_serializable(data):
 
138
  """
139
  html_content += "</div>"
140
  return "<h1>The best technologies combinations </h1>" + html_content
141
+
142
+ def format_prior_art_html(prior_art_data: dict) -> str:
143
+ if not prior_art_data or 'content' not in prior_art_data:
144
+ return "<div class='prior-art-container'><p>No prior art data available.</p></div>"
145
+
146
+ content = prior_art_data['content']
147
+ uris = prior_art_data.get('uris', [])
148
+
149
+ # 1. Convert **text** to <strong>text</strong>
150
+ processed_content = re.sub(r'\*\*(.*?)\*\*', r'<strong>\1</strong>', content)
151
+
152
+ # 2. Convert [x](uri) to clickable links
153
+ # This regex handles cases where [x] is followed by (uri)
154
+ # It captures the number (group 1) and the URI (group 2)
155
+ processed_content = re.sub(r'\[(\d+)\]\((https?:\/\/[^\s\)]+)\)', r'<a href="\2" target="_blank" class="prior-art-inline-link">\1</a>', processed_content)
156
+
157
+ # Split content into initial summary and then document sections
158
+ sections = processed_content.split("Here are the documents found and the technologies used within them:\n\n")
159
+
160
+ summary_html = ""
161
+ documents_html = ""
162
+
163
+ # Process summary part (the first part of the split)
164
+ if len(sections) > 0:
165
+ summary_lines = sections[0].strip().split('\n')
166
+ summary_html += " <div class='prior-art-summary'>\n"
167
+ for line in summary_lines:
168
+ if line.strip().startswith('*'):
169
+ # For bullet points, specially format bold text
170
+ # The bolding for **text** is already handled by re.sub
171
+ parts = line.split(':', 1)
172
+ if len(parts) > 1:
173
+ summary_html += f" <p class='summary-bullet'><strong>{parts[0].replace('*', '').strip()}:</strong> {parts[1].strip()}</p>\n"
174
+ else:
175
+ summary_html += f" <p class='summary-bullet'>{line.replace('*', '').strip()}</p>\n"
176
+ elif line.strip():
177
+ summary_html += f" <p>{line.strip()}</p>\n"
178
+ summary_html += " </div>\n"
179
+
180
+ # Process documents part (the second part of the split)
181
+ if len(sections) > 1:
182
+ documents_raw = sections[1].strip()
183
+ # Split by "number. **" to get individual document entries reliably
184
+ document_entries = re.split(r'(\d+\.\s*\*\*.*?\*\*)', documents_raw)
185
+
186
+ parsed_docs = []
187
+ for i in range(1, len(document_entries), 2):
188
+ title_line = document_entries[i].strip()
189
+ content_block = document_entries[i+1].strip() if i+1 < len(document_entries) else ""
190
+ parsed_docs.append({'title_line': title_line, 'content_block': content_block})
191
+
192
+ documents_html += " <div class='prior-art-documents'>\n"
193
+ for doc in parsed_docs:
194
+ doc_number_title = doc['title_line']
195
+ doc_content_lines = [l.strip() for l in doc['content_block'].split('\n') if l.strip()]
196
+
197
+ doc_description = ""
198
+ tech_used_section = []
199
+
200
+ desc_start_idx = -1
201
+ tech_start_idx = -1
202
+
203
+ for idx, line in enumerate(doc_content_lines):
204
+ if line.startswith("Description:"):
205
+ desc_start_idx = idx
206
+ elif line.startswith("Technologies Used:"):
207
+ tech_start_idx = idx
208
+
209
+ if desc_start_idx != -1:
210
+ desc_end_idx = tech_start_idx if tech_start_idx != -1 else len(doc_content_lines)
211
+ doc_description = " ".join(doc_content_lines[desc_start_idx:desc_end_idx]).replace("Description:", "").strip()
212
+
213
+ if tech_start_idx != -1:
214
+ tech_used_section = [l.replace('*', '').strip() for l in doc_content_lines[tech_start_idx:] if l.strip().startswith('*')]
215
+
216
+
217
+ documents_html += f"""\
218
+ <div class='prior-art-document-card'>
219
+ <h4 class='document-title'>{doc_number_title}</h4>
220
+ <p class='document-description'><strong>Description:</strong> {doc_description}</p>\n"""
221
+ if tech_used_section:
222
+ documents_html += " <div class='document-technologies'>\n"
223
+ documents_html += " <h5>Technologies Used:</h5>\n <ul>\n"
224
+ for tech_item in tech_used_section:
225
+ if tech_item.strip():
226
+ tech_parts = tech_item.split(':', 1)
227
+ if len(tech_parts) > 1:
228
+ documents_html += f" <li><strong>{tech_parts[0].strip()}:</strong> {tech_parts[1].strip()}</li>\n"
229
+ else:
230
+ documents_html += f" <li>{tech_item.strip()}</li>\n"
231
+ documents_html += " </ul>\n </div>\n"
232
+ documents_html += " </div>\n"
233
+ documents_html += " </div>\n"
234
+
235
+ # Grouped URLs at the end
236
+ grouped_uris_html = ""
237
+ if uris:
238
+ grouped_uris_html += " <div class='grouped-uris-section'>\n"
239
+ grouped_uris_html += " <hr class='disruptive-line'>\n" # Disruptive line
240
+ grouped_uris_html += " <h3>Referenced Documents (URIs):</h3>\n"
241
+ grouped_uris_html += " <ul>\n"
242
+ for idx, uri in enumerate(uris):
243
+ grouped_uris_html += f" <li>{idx + 1}. <a href='{uri}' target='_blank' class='prior-art-grouped-link'>Document {idx + 1} Link</a></li>\n"
244
+ grouped_uris_html += " </ul>\n </div>\n"
245
+
246
+ return f"<div class='prior-art-container'>\n{summary_html}{documents_html}{grouped_uris_html}</div>"
247
+
248
+
249
+ def gradio_prior_art(best_technologies, constraints):
250
+ prior_art = process_prior_art(best_technologies, constraints, "constraints", "dict")
251
+ html_prior_art = format_prior_art_html(prior_art)
252
+ print(html_prior_art)
253
+ return html_prior_art
254
+
255
  def process_input_gradio(problem_description: str):
256
  """
257
  Processes the input problem description step-by-step for Gradio.
 
285
 
286
  # Step 8: Get Technologies by ID
287
  best_technologies = get_technologies_by_id(best_technologies_id, global_tech)
 
 
 
 
 
 
288
 
289
  # Format outputs for Gradio
290
  # For Constraints:
 
296
  # For Final Technologies:
297
  final_technologies_html = format_final_technologies_html(best_technologies)
298
 
 
 
 
299
  return (
300
  prompt,
301
  constraints_html, # Output HTML for constraints
302
  best_combinations_html, # Output HTML for best combinations
303
  ", ".join(map(str, best_technologies_id)), # Still a simple text list
304
+ final_technologies_html, # Output HTML for final technologies
305
+ {"technologies": best_technologies}, # `best_technologies` is the actual list of dicts
306
+ constraints
307
  )
308
 
309
+
310
+ # Return a gr.update object to change the value and visibility in one step
311
+ # return gr.update(value=html_prior_art, visible=True)
312
+
313
 
314
  # --- Gradio Interface Setup ---
315
  input_problem = gr.Textbox(
 
322
  output_best_combinations = gr.HTML(label="7. Best Technology Combinations Found") # Changed to HTML
323
  output_selected_ids = gr.Textbox(label="8. Selected Technology IDs", interactive=False)
324
  output_final_technologies = gr.HTML(label="9. Final Best Technologies") # Changed to HTML
325
+ output_prior_art = gr.HTML(label="10. Prior Art Analysis") # Initially hidden
326
+
327
+ stock_technologies = gr.JSON(visible=False)
328
+ stock_constraints = gr.JSON(visible=False)
329
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
330
  with gr.Blocks(
331
  theme=gr.themes.Soft(),
332
  css=custom_css
 
348
  with gr.Row():
349
  with gr.Column():
350
  output_prompt.render()
351
+ output_constraints.render()
352
  with gr.Column():
353
+ output_selected_ids.render()
354
+ output_best_combinations.render()
355
+ output_final_technologies.render()
356
+
357
+ gr.Markdown("---")
358
+ gr.Markdown("### Prior Art Analysis")
359
+ prior_art_button = gr.Button("Find Prior Art", elem_id="prior_art_button")
360
+ output_prior_art.render()
361
+ stock_technologies.render()
362
+ stock_constraints.render()
363
+
364
  process_button.click(
365
  fn=process_input_gradio,
366
  inputs=input_problem,
 
369
  output_constraints,
370
  output_best_combinations,
371
  output_selected_ids,
372
+ output_final_technologies,
373
+ stock_technologies,
374
+ stock_constraints
375
  ]
376
  )
377
 
378
+ prior_art_button.click(
379
+ fn=gradio_prior_art,
380
+ inputs=[stock_technologies, stock_constraints],
381
+ outputs=output_prior_art
382
+ )
383
+
384
+
385
  gr.mount_gradio_app(app, gradio_app_blocks, path="/gradio")
386
  #if __name__ == "__main__":
387
  # gradio_app_blocks.launch()
src/core.py CHANGED
@@ -30,13 +30,13 @@ def process_input(data, global_tech, global_tech_embeddings, data_type):
30
 
31
  return best_technologies
32
 
33
- def process_prior_art(technologies, data, data_type):
34
  try:
35
- prior_art_reponse = search_prior_art(technologies, data, data_type)
36
  prior_art_search = add_citations_and_collect_uris(prior_art_reponse)
37
  except Exception as e:
38
  print(f"An error occured during the process, trying again : {e}")
39
- prior_art_reponse = search_prior_art(technologies, data, data_type)
40
  prior_art_search = add_citations_and_collect_uris(prior_art_reponse)
41
 
42
  return prior_art_search
 
30
 
31
  return best_technologies
32
 
33
+ def process_prior_art(technologies, data, data_type, techno_type):
34
  try:
35
+ prior_art_reponse = search_prior_art(technologies, data, data_type, techno_type)
36
  prior_art_search = add_citations_and_collect_uris(prior_art_reponse)
37
  except Exception as e:
38
  print(f"An error occured during the process, trying again : {e}")
39
+ prior_art_reponse = search_prior_art(technologies, data, data_type, techno_type)
40
  prior_art_search = add_citations_and_collect_uris(prior_art_reponse)
41
 
42
  return prior_art_search
src/services/processor.py CHANGED
@@ -217,19 +217,26 @@ def select_technologies(problem_technology_list):
217
  return set()
218
  return set(best_set)
219
 
220
-
221
- def search_prior_art(technologies_input: list, data: str, type: str) -> json:
 
 
 
 
 
 
 
222
  """
223
  Searches for prior art patents online that solve a given technical problem
224
  using a set of specified technologies, leveraging the Gemini model's search capabilities.
225
  """
226
 
227
- technology_titles = [tech.title for tech in technologies_input]
228
 
229
- if type == "problem":
230
  prompt = f"Find prior art patents or research paper online that address the technical problem: '{data}'. " \
231
 
232
- elif type == "constraints":
233
  prompt = f"Find prior art patents or research paper online that address those constraints: '{data}'. " \
234
 
235
  prompt += f"Using any combination of the following technologies: {', '.join(technology_titles)}. " \
@@ -274,5 +281,4 @@ def add_citations_and_collect_uris(response):
274
  return {"content": text,"uris": list(uris_added)}
275
  except Exception as e:
276
  print(f"Error : {e}")
277
- return {"content": e, "uris": []}
278
-
 
217
  return set()
218
  return set(best_set)
219
 
220
+ def load_titles(techno, data_type):
221
+ if data_type == "pydantic":
222
+ technology_titles = [tech.title for tech in techno]
223
+ else: # data_type == "dict"
224
+ technologies = techno["technologies"]
225
+ technology_titles = [tech["title"] for tech in technologies]
226
+ return technology_titles
227
+
228
+ def search_prior_art(technologies_input: list, data: str, data_type: str, techno_type: str) -> json:
229
  """
230
  Searches for prior art patents online that solve a given technical problem
231
  using a set of specified technologies, leveraging the Gemini model's search capabilities.
232
  """
233
 
234
+ technology_titles = load_titles(technologies_input, techno_type)
235
 
236
+ if data_type == "problem":
237
  prompt = f"Find prior art patents or research paper online that address the technical problem: '{data}'. " \
238
 
239
+ elif data_type == "constraints":
240
  prompt = f"Find prior art patents or research paper online that address those constraints: '{data}'. " \
241
 
242
  prompt += f"Using any combination of the following technologies: {', '.join(technology_titles)}. " \
 
281
  return {"content": text,"uris": list(uris_added)}
282
  except Exception as e:
283
  print(f"Error : {e}")
284
+ return {"content": e, "uris": []}