Spaces:
Sleeping
Sleeping
Zeggai Abdellah
commited on
Commit
·
a6cedca
1
Parent(s):
a043019
fix max iterations
Browse files- rag_pipeline.py +58 -53
rag_pipeline.py
CHANGED
|
@@ -121,7 +121,7 @@ You provide evidence-based guidance using only information from official vaccine
|
|
| 121 |
Answer the doctor's question accurately and concisely using only the provided information.
|
| 122 |
|
| 123 |
## FALLBACK MODE INSTRUCTIONS
|
| 124 |
-
- You have access to only 2 powerful tools:
|
| 125 |
- **MANDATORY TOOL USAGE**: Always use the relevant tool(s) to search for information before answering, even if you initially think no information is available.
|
| 126 |
- Be direct and efficient - search once with each tool if needed, then provide your answer.
|
| 127 |
- Do not overthink or search repeatedly - these tools are comprehensive.
|
|
@@ -132,7 +132,7 @@ Answer the doctor's question accurately and concisely using only the provided in
|
|
| 132 |
1. For each fact in your response, include an inline citation in the format [Source ID] immediately following the information, e.g., [e795ebd28318886c0b1a5395ac30ad90].
|
| 133 |
2. The Source ID must be the exact alphanumeric identifier from the search results, NOT the tool name or any other text.
|
| 134 |
3. Do NOT use 'Source:' in the citation format; use only the Source ID in square brackets.
|
| 135 |
-
4. Do NOT use tool names (like
|
| 136 |
5. If a fact is supported by multiple sources, use adjacent citations: [e795ebd28318886c0b1a5395ac30ad90][21a932b2340bb16707763f57f0ad2]
|
| 137 |
6. Use ONLY the provided information from tool outputs and never include facts from your general knowledge.
|
| 138 |
|
|
@@ -146,20 +146,18 @@ Answer the doctor's question accurately and concisely using only the provided in
|
|
| 146 |
|
| 147 |
### CRITICAL: Efficient Fallback Strategy
|
| 148 |
1. **MANDATORY SEARCH**: Use each relevant tool at least once to search for information, even if you suspect the information might not be available.
|
| 149 |
-
2. **BREAK DOWN COMPLEX QUERIES**: For comparative or multi-part questions (e.g., comparing Algerian and WHO guidelines), break the query into sub-queries and use the appropriate tool for each part
|
| 150 |
-
- Use Guide_vector_tool for Algerian-specific information (e.g., national schedules, coverage targets).
|
| 151 |
-
- Use Immunization_in_Practice_tool for WHO-specific information (e.g., global recommendations, coverage targets).
|
| 152 |
3. **DO NOT STOP PREMATURELY**: Do not conclude "no information is available" without using the relevant tool(s) to search for the answer.
|
| 153 |
4. **BE DECISIVE**: Once you find relevant information for each sub-query, formulate your response immediately.
|
| 154 |
5. **ANSWER FULLY**: Address all parts of the question, using multiple tools if required by the query.
|
|
|
|
| 155 |
|
| 156 |
### Response Guidelines
|
| 157 |
- **MANDATORY TOOL SELECTION**:
|
| 158 |
-
- For queries mentioning "WHO," "World Health Organization," "international," "global guidance," or WHO documents
|
| 159 |
-
- For queries mentioning "Algerian," "national guide," or Algerian-specific terms
|
| 160 |
-
- For comparative queries (e.g., Algerian vs. WHO), use both
|
| 161 |
- **EXPLICIT REASONING**: Before answering, log your reasoning steps, including which tools you will use and why, based on the query’s content.
|
| 162 |
-
- **Query Decomposition**: Break comparative or multi-part queries into sub-queries (e.g., one for Algerian information, one for WHO information) and use the appropriate tool for each.
|
| 163 |
- Provide all found information with proper citations using Source IDs only.
|
| 164 |
- If information is limited, clearly state: "Based on the available documents, I can provide the following information..." and indicate what is not available.
|
| 165 |
|
|
@@ -178,7 +176,7 @@ Answer the doctor's question accurately and concisely using only the provided in
|
|
| 178 |
1. For each fact in your response, include an inline citation in the format [Source ID] immediately following the information, e.g., [e795ebd28318886c0b1a5395ac30ad90].
|
| 179 |
2. The Source ID must be the exact alphanumeric identifier from the search results, NOT the tool name or any other text.
|
| 180 |
3. Do NOT use 'Source:' in the citation format; use only the Source ID in square brackets.
|
| 181 |
-
4. Do NOT use tool names (like
|
| 182 |
5. If a fact is supported by multiple sources, use adjacent citations: [e795ebd28318886c0b1a5395ac30ad90][21a932b2340bb16707763f57f0ad2]
|
| 183 |
6. Use ONLY the provided information from tool outputs and never include facts from your general knowledge.
|
| 184 |
|
|
@@ -193,28 +191,23 @@ Answer the doctor's question accurately and concisely using only the provided in
|
|
| 193 |
### CRITICAL: Efficient Response Strategy
|
| 194 |
1. **MANDATORY SEARCH**: Always use the relevant tool(s) to search for information before answering, even if you initially think no information is available.
|
| 195 |
2. **MANDATORY TOOL SELECTION**:
|
| 196 |
-
- For queries
|
| 197 |
-
- For
|
| 198 |
-
- For
|
| 199 |
-
3. **Query Decomposition**: Break comparative or multi-part queries into sub-queries
|
| 200 |
4. **DO NOT STOP PREMATURELY**: Do not conclude "no information is available" without using the relevant tool(s) to search for the answer.
|
| 201 |
-
5. **EXPLICIT REASONING**: Before answering, log your reasoning steps, including which tools you will use and why
|
| 202 |
-
6. **BE DECISIVE**: Once you find relevant information
|
| 203 |
-
|
| 204 |
-
|
|
|
|
|
|
|
|
|
|
| 205 |
|
| 206 |
### Response Guidelines for Complex Questions
|
| 207 |
-
- For comparative questions: Break the query into sub-queries
|
| 208 |
- For multi-part questions: Address each part systematically, using the appropriate tool for each sub-query.
|
| 209 |
- If information is not found after using the relevant tool(s): State clearly: "Based on the available documents, I can provide the following information..." and specify what is not available.
|
| 210 |
-
- Do not repeatedly search for the same terms or rephrase searches excessively.
|
| 211 |
-
|
| 212 |
-
### When Information is Limited
|
| 213 |
-
If you cannot find complete information to fully answer a question:
|
| 214 |
-
1. Provide whatever relevant information you did find with proper citations using Source IDs only.
|
| 215 |
-
2. Clearly state: "Based on the available documents, I can provide the following information..."
|
| 216 |
-
3. Indicate what specific information is not available: "However, information about [specific topic] was not found in the provided documents after searching with the relevant tool(s)."
|
| 217 |
-
4. Do not conclude "no information is available" without attempting a search with the appropriate tool(s).
|
| 218 |
|
| 219 |
---
|
| 220 |
"""
|
|
@@ -248,7 +241,8 @@ def create_agent(tools, llm, is_fallback=False):
|
|
| 248 |
"""Create the ReAct agent with custom prompt"""
|
| 249 |
|
| 250 |
agent_type = "FALLBACK" if is_fallback else "STANDARD"
|
| 251 |
-
|
|
|
|
| 252 |
|
| 253 |
print(f"[LOG] Creating {agent_type} ReAct agent with {len(tools)} tools and max_iterations={max_iter}")
|
| 254 |
|
|
@@ -257,7 +251,7 @@ def create_agent(tools, llm, is_fallback=False):
|
|
| 257 |
tools,
|
| 258 |
llm=llm,
|
| 259 |
verbose=True,
|
| 260 |
-
max_iterations=max_iter,
|
| 261 |
)
|
| 262 |
|
| 263 |
# Create and apply safe custom prompt
|
|
@@ -274,9 +268,9 @@ def create_agent(tools, llm, is_fallback=False):
|
|
| 274 |
|
| 275 |
|
| 276 |
def create_fallback_tools(all_tools):
|
| 277 |
-
"""Extract only the
|
| 278 |
|
| 279 |
-
print("[LOG] Creating fallback tools (guide +
|
| 280 |
|
| 281 |
fallback_tools = []
|
| 282 |
tool_names_found = []
|
|
@@ -334,7 +328,14 @@ def initialize_rag_pipeline(tools):
|
|
| 334 |
|
| 335 |
|
| 336 |
def detect_max_iterations_error(response_text):
|
| 337 |
-
"""Detect if the response indicates a max iterations error"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 338 |
|
| 339 |
max_iteration_indicators = [
|
| 340 |
"max iterations",
|
|
@@ -344,11 +345,10 @@ def detect_max_iterations_error(response_text):
|
|
| 344 |
"iteration limit"
|
| 345 |
]
|
| 346 |
|
| 347 |
-
|
| 348 |
-
|
| 349 |
-
# Check for max iterations indicators
|
| 350 |
for indicator in max_iteration_indicators:
|
| 351 |
if indicator in response_lower:
|
|
|
|
| 352 |
return True
|
| 353 |
|
| 354 |
# Check for very short or empty responses (often indicates failure)
|
|
@@ -389,7 +389,7 @@ def process_question(agents_dict, question: str) -> str:
|
|
| 389 |
|
| 390 |
# Check if we need to use fallback
|
| 391 |
if detect_max_iterations_error(response_text):
|
| 392 |
-
print("[LOG] 🔄 Max iterations detected, switching to FALLBACK AGENT...")
|
| 393 |
|
| 394 |
if fallback_agent is None:
|
| 395 |
print("[LOG] ❌ Fallback agent not available, returning error message")
|
|
@@ -419,7 +419,7 @@ def process_question(agents_dict, question: str) -> str:
|
|
| 419 |
|
| 420 |
# Check if fallback also failed
|
| 421 |
if detect_max_iterations_error(fallback_text):
|
| 422 |
-
print("[LOG] ❌ Fallback agent also hit max iterations")
|
| 423 |
return ("I apologize, but I'm having difficulty finding specific information about your question in the available documents. "
|
| 424 |
"Please try asking a more specific question or rephrasing your query.")
|
| 425 |
|
|
@@ -501,16 +501,17 @@ def process_question_with_sequential_citations(agents_dict, question: str, chunk
|
|
| 501 |
print(f"[LOG] Chunks directory: {chunks_directory}")
|
| 502 |
start_time = time.time()
|
| 503 |
|
| 504 |
-
used_fallback = False
|
| 505 |
|
| 506 |
try:
|
| 507 |
# Get the response using the enhanced process_question function
|
| 508 |
response_text = process_question(agents_dict, question)
|
| 509 |
|
| 510 |
-
# Check if
|
| 511 |
-
|
|
|
|
| 512 |
used_fallback = True
|
| 513 |
-
print("[LOG] 🛡️ Fallback agent was likely used")
|
| 514 |
|
| 515 |
agent_time = time.time() - start_time
|
| 516 |
print(f"[LOG] Agent processing completed in {agent_time:.2f} seconds")
|
|
@@ -534,6 +535,10 @@ def process_question_with_sequential_citations(agents_dict, question: str, chunk
|
|
| 534 |
|
| 535 |
for json_file in min_chunks_files:
|
| 536 |
json_path = os.path.join(chunks_directory, json_file)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 537 |
print(f"[LOG] Loading {json_file}...")
|
| 538 |
try:
|
| 539 |
with open(json_path, "r", encoding="utf-8") as f:
|
|
@@ -549,23 +554,23 @@ def process_question_with_sequential_citations(agents_dict, question: str, chunk
|
|
| 549 |
print("[LOG] Finding cited elements...")
|
| 550 |
cited_elements_ordered = []
|
| 551 |
for i, source_id in enumerate(unique_ids): # This preserves the order
|
| 552 |
-
print(f"[LOG] Looking for source ID {i+1}/{len(unique_ids)}: {source_id}")
|
| 553 |
found = False
|
| 554 |
for element in all_chunks_data:
|
|
|
|
| 555 |
if element.get("type") == 'TableElement':
|
| 556 |
-
if element.get("elements",{}).get("element_id") == source_id:
|
| 557 |
-
cited_elements_ordered.append(element.get("elements",{}))
|
| 558 |
found = True
|
| 559 |
break
|
| 560 |
-
|
| 561 |
-
|
| 562 |
-
|
| 563 |
-
|
| 564 |
-
|
| 565 |
-
|
| 566 |
-
|
| 567 |
-
|
| 568 |
-
continue
|
| 569 |
break
|
| 570 |
if not found:
|
| 571 |
print(f"[LOG] ⚠️ Source ID {source_id} not found in chunks data")
|
|
|
|
| 121 |
Answer the doctor's question accurately and concisely using only the provided information.
|
| 122 |
|
| 123 |
## FALLBACK MODE INSTRUCTIONS
|
| 124 |
+
- You have access to only 2 powerful tools: general_guide_tool (Algerian National Vaccination Guide) and who_immunization_tool (WHO global guidance).
|
| 125 |
- **MANDATORY TOOL USAGE**: Always use the relevant tool(s) to search for information before answering, even if you initially think no information is available.
|
| 126 |
- Be direct and efficient - search once with each tool if needed, then provide your answer.
|
| 127 |
- Do not overthink or search repeatedly - these tools are comprehensive.
|
|
|
|
| 132 |
1. For each fact in your response, include an inline citation in the format [Source ID] immediately following the information, e.g., [e795ebd28318886c0b1a5395ac30ad90].
|
| 133 |
2. The Source ID must be the exact alphanumeric identifier from the search results, NOT the tool name or any other text.
|
| 134 |
3. Do NOT use 'Source:' in the citation format; use only the Source ID in square brackets.
|
| 135 |
+
4. Do NOT use tool names (like general_guide_tool, who_immunization_tool) as citations.
|
| 136 |
5. If a fact is supported by multiple sources, use adjacent citations: [e795ebd28318886c0b1a5395ac30ad90][21a932b2340bb16707763f57f0ad2]
|
| 137 |
6. Use ONLY the provided information from tool outputs and never include facts from your general knowledge.
|
| 138 |
|
|
|
|
| 146 |
|
| 147 |
### CRITICAL: Efficient Fallback Strategy
|
| 148 |
1. **MANDATORY SEARCH**: Use each relevant tool at least once to search for information, even if you suspect the information might not be available.
|
| 149 |
+
2. **BREAK DOWN COMPLEX QUERIES**: For comparative or multi-part questions (e.g., comparing Algerian and WHO guidelines), break the query into sub-queries and use the appropriate tool for each part.
|
|
|
|
|
|
|
| 150 |
3. **DO NOT STOP PREMATURELY**: Do not conclude "no information is available" without using the relevant tool(s) to search for the answer.
|
| 151 |
4. **BE DECISIVE**: Once you find relevant information for each sub-query, formulate your response immediately.
|
| 152 |
5. **ANSWER FULLY**: Address all parts of the question, using multiple tools if required by the query.
|
| 153 |
+
6. **FINAL ANSWER**: Once you have your answer, present it directly. Do not output your internal 'thought' or 'action' steps. Your final output must be the synthesized answer itself.
|
| 154 |
|
| 155 |
### Response Guidelines
|
| 156 |
- **MANDATORY TOOL SELECTION**:
|
| 157 |
+
- For queries mentioning "WHO," "World Health Organization," "international," "global guidance," or WHO documents, use who_immunization_tool first.
|
| 158 |
+
- For queries mentioning "Algerian," "national guide," or Algerian-specific terms, use general_guide_tool first.
|
| 159 |
+
- For comparative queries (e.g., Algerian vs. WHO), use both tools, addressing each part systematically.
|
| 160 |
- **EXPLICIT REASONING**: Before answering, log your reasoning steps, including which tools you will use and why, based on the query’s content.
|
|
|
|
| 161 |
- Provide all found information with proper citations using Source IDs only.
|
| 162 |
- If information is limited, clearly state: "Based on the available documents, I can provide the following information..." and indicate what is not available.
|
| 163 |
|
|
|
|
| 176 |
1. For each fact in your response, include an inline citation in the format [Source ID] immediately following the information, e.g., [e795ebd28318886c0b1a5395ac30ad90].
|
| 177 |
2. The Source ID must be the exact alphanumeric identifier from the search results, NOT the tool name or any other text.
|
| 178 |
3. Do NOT use 'Source:' in the citation format; use only the Source ID in square brackets.
|
| 179 |
+
4. Do NOT use tool names (like general_guide_tool, cold_chain_tool) as citations.
|
| 180 |
5. If a fact is supported by multiple sources, use adjacent citations: [e795ebd28318886c0b1a5395ac30ad90][21a932b2340bb16707763f57f0ad2]
|
| 181 |
6. Use ONLY the provided information from tool outputs and never include facts from your general knowledge.
|
| 182 |
|
|
|
|
| 191 |
### CRITICAL: Efficient Response Strategy
|
| 192 |
1. **MANDATORY SEARCH**: Always use the relevant tool(s) to search for information before answering, even if you initially think no information is available.
|
| 193 |
2. **MANDATORY TOOL SELECTION**:
|
| 194 |
+
- For queries about global standards or WHO, use who_immunization_tool.
|
| 195 |
+
- For broad questions about the Algerian guide, use general_guide_tool.
|
| 196 |
+
- For specific topics like cold chain, disease info, etc., use the most specific tool (e.g., cold_chain_tool, disease_info_tool).
|
| 197 |
+
3. **Query Decomposition**: Break comparative or multi-part queries into sub-queries and use the appropriate tool for each.
|
| 198 |
4. **DO NOT STOP PREMATURELY**: Do not conclude "no information is available" without using the relevant tool(s) to search for the answer.
|
| 199 |
+
5. **EXPLICIT REASONING**: Before answering, log your reasoning steps, including which tools you will use and why.
|
| 200 |
+
6. **BE DECISIVE**: Once you find relevant information, formulate your response.
|
| 201 |
+
|
| 202 |
+
### Final Answer Generation
|
| 203 |
+
- **STOP WHEN SUFFICIENT**: Once you have gathered enough information from the tools to answer the user's question completely, you MUST stop using tools and formulate a final answer.
|
| 204 |
+
- **SYNTHESIZE THE ANSWER**: Formulate a comprehensive, final answer based ONLY on the observed tool outputs.
|
| 205 |
+
- **PRESENT CLEANLY**: Present this final answer directly to the user. Your final output must be the answer itself, not your internal 'thought' or 'action' steps.
|
| 206 |
|
| 207 |
### Response Guidelines for Complex Questions
|
| 208 |
+
- For comparative questions: Break the query into sub-queries, use the appropriate tools, then provide the comparison.
|
| 209 |
- For multi-part questions: Address each part systematically, using the appropriate tool for each sub-query.
|
| 210 |
- If information is not found after using the relevant tool(s): State clearly: "Based on the available documents, I can provide the following information..." and specify what is not available.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 211 |
|
| 212 |
---
|
| 213 |
"""
|
|
|
|
| 241 |
"""Create the ReAct agent with custom prompt"""
|
| 242 |
|
| 243 |
agent_type = "FALLBACK" if is_fallback else "STANDARD"
|
| 244 |
+
# **FIX**: Increased max_iterations to give the agent more steps to reason
|
| 245 |
+
max_iter = 15
|
| 246 |
|
| 247 |
print(f"[LOG] Creating {agent_type} ReAct agent with {len(tools)} tools and max_iterations={max_iter}")
|
| 248 |
|
|
|
|
| 251 |
tools,
|
| 252 |
llm=llm,
|
| 253 |
verbose=True,
|
| 254 |
+
max_iterations=max_iter,
|
| 255 |
)
|
| 256 |
|
| 257 |
# Create and apply safe custom prompt
|
|
|
|
| 268 |
|
| 269 |
|
| 270 |
def create_fallback_tools(all_tools):
|
| 271 |
+
"""Extract only the general_guide_tool and who_immunization_tool for fallback agent"""
|
| 272 |
|
| 273 |
+
print("[LOG] Creating fallback tools (guide + WHO only)")
|
| 274 |
|
| 275 |
fallback_tools = []
|
| 276 |
tool_names_found = []
|
|
|
|
| 328 |
|
| 329 |
|
| 330 |
def detect_max_iterations_error(response_text):
|
| 331 |
+
"""Detect if the response indicates a max iterations error OR is an unfinished thought."""
|
| 332 |
+
|
| 333 |
+
response_lower = response_text.lower().strip()
|
| 334 |
+
|
| 335 |
+
# **FIX**: Check if the response is the agent's raw thought process.
|
| 336 |
+
if response_lower.startswith("a:```thought") or response_lower.startswith("```thought"):
|
| 337 |
+
print("[LOG] Detected unfinished agent thought process.")
|
| 338 |
+
return True
|
| 339 |
|
| 340 |
max_iteration_indicators = [
|
| 341 |
"max iterations",
|
|
|
|
| 345 |
"iteration limit"
|
| 346 |
]
|
| 347 |
|
| 348 |
+
# Check for explicit max iterations indicators
|
|
|
|
|
|
|
| 349 |
for indicator in max_iteration_indicators:
|
| 350 |
if indicator in response_lower:
|
| 351 |
+
print(f"[LOG] Detected max iteration indicator: '{indicator}'")
|
| 352 |
return True
|
| 353 |
|
| 354 |
# Check for very short or empty responses (often indicates failure)
|
|
|
|
| 389 |
|
| 390 |
# Check if we need to use fallback
|
| 391 |
if detect_max_iterations_error(response_text):
|
| 392 |
+
print("[LOG] 🔄 Max iterations or unfinished thought detected, switching to FALLBACK AGENT...")
|
| 393 |
|
| 394 |
if fallback_agent is None:
|
| 395 |
print("[LOG] ❌ Fallback agent not available, returning error message")
|
|
|
|
| 419 |
|
| 420 |
# Check if fallback also failed
|
| 421 |
if detect_max_iterations_error(fallback_text):
|
| 422 |
+
print("[LOG] ❌ Fallback agent also hit max iterations or failed to produce an answer.")
|
| 423 |
return ("I apologize, but I'm having difficulty finding specific information about your question in the available documents. "
|
| 424 |
"Please try asking a more specific question or rephrasing your query.")
|
| 425 |
|
|
|
|
| 501 |
print(f"[LOG] Chunks directory: {chunks_directory}")
|
| 502 |
start_time = time.time()
|
| 503 |
|
| 504 |
+
used_fallback = False # This flag is a heuristic
|
| 505 |
|
| 506 |
try:
|
| 507 |
# Get the response using the enhanced process_question function
|
| 508 |
response_text = process_question(agents_dict, question)
|
| 509 |
|
| 510 |
+
# Check if fallback was likely used (simple heuristic based on logs)
|
| 511 |
+
# A more robust way would be for `process_question` to return a tuple (response, used_fallback)
|
| 512 |
+
if "switching to fallback agent" in response_text.lower():
|
| 513 |
used_fallback = True
|
| 514 |
+
print("[LOG] 🛡️ Fallback agent was likely used based on log indicators.")
|
| 515 |
|
| 516 |
agent_time = time.time() - start_time
|
| 517 |
print(f"[LOG] Agent processing completed in {agent_time:.2f} seconds")
|
|
|
|
| 535 |
|
| 536 |
for json_file in min_chunks_files:
|
| 537 |
json_path = os.path.join(chunks_directory, json_file)
|
| 538 |
+
if not os.path.exists(json_path):
|
| 539 |
+
print(f"[LOG] ⚠️ Skipping non-existent file: {json_path}")
|
| 540 |
+
continue
|
| 541 |
+
|
| 542 |
print(f"[LOG] Loading {json_file}...")
|
| 543 |
try:
|
| 544 |
with open(json_path, "r", encoding="utf-8") as f:
|
|
|
|
| 554 |
print("[LOG] Finding cited elements...")
|
| 555 |
cited_elements_ordered = []
|
| 556 |
for i, source_id in enumerate(unique_ids): # This preserves the order
|
| 557 |
+
# print(f"[LOG] Looking for source ID {i+1}/{len(unique_ids)}: {source_id}") # This is too verbose for normal operation
|
| 558 |
found = False
|
| 559 |
for element in all_chunks_data:
|
| 560 |
+
# Handle TableElement structure
|
| 561 |
if element.get("type") == 'TableElement':
|
| 562 |
+
if element.get("elements", {}).get("element_id") == source_id:
|
| 563 |
+
cited_elements_ordered.append(element.get("elements", {}))
|
| 564 |
found = True
|
| 565 |
break
|
| 566 |
+
# Handle other element structures
|
| 567 |
+
elif "elements" in element and isinstance(element["elements"], list):
|
| 568 |
+
for nested_element in element["elements"]:
|
| 569 |
+
if isinstance(nested_element, dict) and nested_element.get("element_id") == source_id:
|
| 570 |
+
cited_elements_ordered.append(nested_element)
|
| 571 |
+
found = True
|
| 572 |
+
break
|
| 573 |
+
if found:
|
|
|
|
| 574 |
break
|
| 575 |
if not found:
|
| 576 |
print(f"[LOG] ⚠️ Source ID {source_id} not found in chunks data")
|