Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -221,6 +221,7 @@ class ResearchRetriever:
|
|
221 |
def retrieve(self, query: str, domain: str) -> List[Any]:
|
222 |
"""
|
223 |
Retrieves documents based on the query and domain.
|
|
|
224 |
"""
|
225 |
try:
|
226 |
return self.research_retriever.invoke(query)
|
@@ -235,8 +236,7 @@ retriever = ResearchRetriever()
|
|
235 |
# ------------------------------
|
236 |
class CognitiveProcessor:
|
237 |
"""
|
238 |
-
Executes API requests to the
|
239 |
-
and consolidates results via a consensus mechanism.
|
240 |
"""
|
241 |
def __init__(self) -> None:
|
242 |
self.executor = ThreadPoolExecutor(max_workers=ResearchConfig.MAX_CONCURRENT_REQUESTS)
|
@@ -260,7 +260,7 @@ class CognitiveProcessor:
|
|
260 |
|
261 |
def _execute_api_request(self, prompt: str) -> Dict:
|
262 |
"""
|
263 |
-
Executes a single API request to the
|
264 |
"""
|
265 |
headers = {
|
266 |
"Authorization": f"Bearer {ResearchConfig.DEEPSEEK_API_KEY}",
|
@@ -285,10 +285,10 @@ class CognitiveProcessor:
|
|
285 |
timeout=45
|
286 |
)
|
287 |
response.raise_for_status()
|
288 |
-
logger.info("
|
289 |
return response.json()
|
290 |
except requests.exceptions.RequestException as e:
|
291 |
-
logger.exception("
|
292 |
return {"error": str(e)}
|
293 |
|
294 |
def _consensus_check(self, results: List[Dict]) -> Dict:
|
@@ -437,7 +437,7 @@ class MultiModalRetriever:
|
|
437 |
return self.code_retriever.invoke(query)
|
438 |
|
439 |
# ------------------------------
|
440 |
-
#
|
441 |
# ------------------------------
|
442 |
class ResearchWorkflow:
|
443 |
"""
|
@@ -472,9 +472,6 @@ class ResearchWorkflow:
|
|
472 |
self.workflow.add_edge("enhance", END)
|
473 |
|
474 |
def ingest_query(self, state: AgentState) -> Dict:
|
475 |
-
"""
|
476 |
-
Ingests the research query and initializes context with query, domain, refinement counter, and history.
|
477 |
-
"""
|
478 |
try:
|
479 |
query = state["messages"][-1].content
|
480 |
domain = state.get("domain", "Biomedical Research")
|
@@ -490,9 +487,6 @@ class ResearchWorkflow:
|
|
490 |
return self._error_state(f"Ingestion Error: {str(e)}")
|
491 |
|
492 |
def retrieve_documents(self, state: AgentState) -> Dict:
|
493 |
-
"""
|
494 |
-
Retrieves research documents based on the query.
|
495 |
-
"""
|
496 |
try:
|
497 |
query = state["context"]["raw_query"]
|
498 |
docs = retriever.retrieve(query, state["context"].get("domain", "Biomedical Research"))
|
@@ -513,37 +507,104 @@ class ResearchWorkflow:
|
|
513 |
|
514 |
def analyze_content(self, state: AgentState) -> Dict:
|
515 |
"""
|
516 |
-
Analyzes the retrieved documents
|
517 |
-
Augments the prompt with domain-specific instructions.
|
518 |
"""
|
519 |
try:
|
520 |
-
docs = state["context"].get("documents", [])
|
521 |
-
docs_text = "\n\n".join([d.page_content for d in docs])
|
522 |
domain = state["context"].get("domain", "Biomedical Research")
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
538 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
539 |
except Exception as e:
|
540 |
logger.exception("Error during content analysis.")
|
541 |
return self._error_state(f"Analysis Error: {str(e)}")
|
542 |
|
543 |
def validate_output(self, state: AgentState) -> Dict:
|
544 |
-
"""
|
545 |
-
Validates the technical analysis report.
|
546 |
-
"""
|
547 |
try:
|
548 |
analysis = state["messages"][-1].content
|
549 |
validation_prompt = (
|
@@ -561,12 +622,6 @@ class ResearchWorkflow:
|
|
561 |
return self._error_state(f"Validation Error: {str(e)}")
|
562 |
|
563 |
def refine_results(self, state: AgentState) -> Dict:
|
564 |
-
"""
|
565 |
-
Refines the analysis report if validation fails.
|
566 |
-
Implements a meta-refinement mechanism inspired by LADDER.
|
567 |
-
Tracks refinement history, uses a dynamic difficulty gradient, and if the refinement count exceeds a threshold,
|
568 |
-
summarizes the history into a final output.
|
569 |
-
"""
|
570 |
try:
|
571 |
current_count = state["context"].get("refine_count", 0)
|
572 |
state["context"]["refine_count"] = current_count + 1
|
@@ -605,13 +660,9 @@ class ResearchWorkflow:
|
|
605 |
return self._error_state(f"Refinement Error: {str(e)}")
|
606 |
|
607 |
def _quality_check(self, state: AgentState) -> str:
|
608 |
-
"""
|
609 |
-
Checks whether the analysis report is valid.
|
610 |
-
Forces a valid state if the refinement count exceeds a threshold.
|
611 |
-
"""
|
612 |
refine_count = state["context"].get("refine_count", 0)
|
613 |
if refine_count >= 3:
|
614 |
-
logger.warning("Refinement limit reached. Forcing valid outcome
|
615 |
return "valid"
|
616 |
content = state["messages"][-1].content
|
617 |
quality = "valid" if "VALID" in content else "invalid"
|
@@ -619,9 +670,6 @@ class ResearchWorkflow:
|
|
619 |
return quality
|
620 |
|
621 |
def _error_state(self, message: str) -> Dict:
|
622 |
-
"""
|
623 |
-
Returns a standardized error state.
|
624 |
-
"""
|
625 |
logger.error(message)
|
626 |
return {
|
627 |
"messages": [AIMessage(content=f"❌ {message}")],
|
@@ -637,12 +685,10 @@ class ResearchWorkflow:
|
|
637 |
try:
|
638 |
analysis = state["messages"][-1].content
|
639 |
enhanced = f"{analysis}\n\n## Multi-Modal Insights\n"
|
640 |
-
# Append image captions if available
|
641 |
if "images" in state["context"]:
|
642 |
enhanced += "### Visual Evidence\n"
|
643 |
for img in state["context"]["images"]:
|
644 |
enhanced += f"\n"
|
645 |
-
# Append code snippets if available
|
646 |
if "code" in state["context"]:
|
647 |
enhanced += "### Code Artifacts\n```python\n"
|
648 |
for code in state["context"]["code"]:
|
@@ -657,12 +703,11 @@ class ResearchWorkflow:
|
|
657 |
return self._error_state(f"Enhancement Error: {str(e)}")
|
658 |
|
659 |
# ------------------------------
|
660 |
-
#
|
661 |
# ------------------------------
|
662 |
class ResearchInterface:
|
663 |
"""
|
664 |
Provides the Streamlit-based interface for executing the research workflow.
|
665 |
-
Extended with collaboration features and knowledge visualization.
|
666 |
"""
|
667 |
def __init__(self) -> None:
|
668 |
self.workflow = ResearchWorkflow()
|
@@ -743,11 +788,7 @@ class ResearchInterface:
|
|
743 |
|
744 |
def _build_main_interface(self) -> None:
|
745 |
st.title("🧠 NeuroResearch AI")
|
746 |
-
query = st.text_area(
|
747 |
-
"Research Query:",
|
748 |
-
height=200,
|
749 |
-
placeholder="Enter technical research question..."
|
750 |
-
)
|
751 |
domain = st.selectbox(
|
752 |
"Select Research Domain:",
|
753 |
options=[
|
@@ -765,11 +806,14 @@ class ResearchInterface:
|
|
765 |
def _execute_analysis(self, query: str, domain: str) -> None:
|
766 |
try:
|
767 |
with st.spinner("Initializing Quantum Analysis..."):
|
768 |
-
results = self.workflow.app.stream(
|
769 |
-
|
770 |
-
|
771 |
-
|
772 |
-
|
|
|
|
|
|
|
773 |
for event in results:
|
774 |
self._render_event(event)
|
775 |
st.success("✅ Analysis Completed Successfully")
|
@@ -819,8 +863,8 @@ Potential issues:
|
|
819 |
st.markdown(content)
|
820 |
|
821 |
def _display_knowledge_graph(self) -> None:
|
822 |
-
graph
|
823 |
-
st.
|
824 |
|
825 |
# ------------------------------
|
826 |
# Multi-Modal Retriever Initialization
|
|
|
221 |
def retrieve(self, query: str, domain: str) -> List[Any]:
|
222 |
"""
|
223 |
Retrieves documents based on the query and domain.
|
224 |
+
For demonstration, always using the "research" retriever.
|
225 |
"""
|
226 |
try:
|
227 |
return self.research_retriever.invoke(query)
|
|
|
236 |
# ------------------------------
|
237 |
class CognitiveProcessor:
|
238 |
"""
|
239 |
+
Executes API requests to the backend using triple redundancy and consolidates results via a consensus mechanism.
|
|
|
240 |
"""
|
241 |
def __init__(self) -> None:
|
242 |
self.executor = ThreadPoolExecutor(max_workers=ResearchConfig.MAX_CONCURRENT_REQUESTS)
|
|
|
260 |
|
261 |
def _execute_api_request(self, prompt: str) -> Dict:
|
262 |
"""
|
263 |
+
Executes a single API request to the backend endpoint.
|
264 |
"""
|
265 |
headers = {
|
266 |
"Authorization": f"Bearer {ResearchConfig.DEEPSEEK_API_KEY}",
|
|
|
285 |
timeout=45
|
286 |
)
|
287 |
response.raise_for_status()
|
288 |
+
logger.info("Backend API request successful.")
|
289 |
return response.json()
|
290 |
except requests.exceptions.RequestException as e:
|
291 |
+
logger.exception("Backend API request failed.")
|
292 |
return {"error": str(e)}
|
293 |
|
294 |
def _consensus_check(self, results: List[Dict]) -> Dict:
|
|
|
437 |
return self.code_retriever.invoke(query)
|
438 |
|
439 |
# ------------------------------
|
440 |
+
# Research Workflow
|
441 |
# ------------------------------
|
442 |
class ResearchWorkflow:
|
443 |
"""
|
|
|
472 |
self.workflow.add_edge("enhance", END)
|
473 |
|
474 |
def ingest_query(self, state: AgentState) -> Dict:
|
|
|
|
|
|
|
475 |
try:
|
476 |
query = state["messages"][-1].content
|
477 |
domain = state.get("domain", "Biomedical Research")
|
|
|
487 |
return self._error_state(f"Ingestion Error: {str(e)}")
|
488 |
|
489 |
def retrieve_documents(self, state: AgentState) -> Dict:
|
|
|
|
|
|
|
490 |
try:
|
491 |
query = state["context"]["raw_query"]
|
492 |
docs = retriever.retrieve(query, state["context"].get("domain", "Biomedical Research"))
|
|
|
507 |
|
508 |
def analyze_content(self, state: AgentState) -> Dict:
|
509 |
"""
|
510 |
+
Analyzes the retrieved documents. Injects a domain-specific fallback analysis for each supported domain.
|
|
|
511 |
"""
|
512 |
try:
|
|
|
|
|
513 |
domain = state["context"].get("domain", "Biomedical Research")
|
514 |
+
query = state["context"].get("raw_query", "")
|
515 |
+
fallback_analyses = {
|
516 |
+
"Biomedical Research": """
|
517 |
+
# Biomedical Research Analysis
|
518 |
+
## Key Contributions
|
519 |
+
- Integration of clinical trial design with digital biomarkers.
|
520 |
+
- Multi-omics data used for precise patient stratification.
|
521 |
+
## Methodologies
|
522 |
+
- Machine learning for precision medicine.
|
523 |
+
- Federated learning for multi-center trials.
|
524 |
+
## Empirical Results
|
525 |
+
- Significant improvements in patient outcomes.
|
526 |
+
## Applications
|
527 |
+
- Personalized medicine, early diagnosis, treatment optimization.
|
528 |
+
""",
|
529 |
+
"Legal Research": """
|
530 |
+
# Legal Research Analysis
|
531 |
+
## Key Contributions
|
532 |
+
- Analysis of legal precedents using NLP.
|
533 |
+
- Advanced case law retrieval and summarization.
|
534 |
+
## Methodologies
|
535 |
+
- Automated legal reasoning with transformer models.
|
536 |
+
- Sentiment analysis on judicial opinions.
|
537 |
+
## Empirical Results
|
538 |
+
- Improved accuracy in predicting case outcomes.
|
539 |
+
## Applications
|
540 |
+
- Legal analytics, risk assessment, regulatory compliance.
|
541 |
+
""",
|
542 |
+
"Environmental and Energy Studies": """
|
543 |
+
# Environmental and Energy Studies Analysis
|
544 |
+
## Key Contributions
|
545 |
+
- Novel approaches to renewable energy efficiency.
|
546 |
+
- Integration of policy analysis with technical metrics.
|
547 |
+
## Methodologies
|
548 |
+
- Simulation models for climate impact.
|
549 |
+
- Data fusion from sensor networks and satellite imagery.
|
550 |
+
## Empirical Results
|
551 |
+
- Enhanced performance in energy forecasting.
|
552 |
+
## Applications
|
553 |
+
- Sustainable urban planning, energy policy formulation.
|
554 |
+
""",
|
555 |
+
"Competitive Programming and Theoretical Computer Science": """
|
556 |
+
# Competitive Programming & Theoretical CS Analysis
|
557 |
+
## Key Contributions
|
558 |
+
- Advanced approximation algorithms for NP-hard problems.
|
559 |
+
- Use of parameterized complexity and fixed-parameter tractability.
|
560 |
+
## Methodologies
|
561 |
+
- Branch-and-bound with dynamic programming.
|
562 |
+
- Quantum-inspired algorithms for optimization.
|
563 |
+
## Empirical Results
|
564 |
+
- Significant improvements in computational efficiency.
|
565 |
+
## Applications
|
566 |
+
- Optimization in competitive programming and algorithm design.
|
567 |
+
""",
|
568 |
+
"Social Sciences": """
|
569 |
+
# Social Sciences Analysis
|
570 |
+
## Key Contributions
|
571 |
+
- Identification of economic trends through data analytics.
|
572 |
+
- Integration of sociological data with computational models.
|
573 |
+
## Methodologies
|
574 |
+
- Advanced statistical modeling for behavioral analysis.
|
575 |
+
- Machine learning for trend forecasting.
|
576 |
+
## Empirical Results
|
577 |
+
- High correlation with traditional survey methods.
|
578 |
+
## Applications
|
579 |
+
- Policy design, urban studies, social impact analysis.
|
580 |
+
"""
|
581 |
}
|
582 |
+
|
583 |
+
if domain in fallback_analyses:
|
584 |
+
logger.info(f"Using fallback analysis for domain: {domain}")
|
585 |
+
return {
|
586 |
+
"messages": [AIMessage(content=fallback_analyses[domain].strip())],
|
587 |
+
"context": state["context"]
|
588 |
+
}
|
589 |
+
else:
|
590 |
+
docs = state["context"].get("documents", [])
|
591 |
+
docs_text = "\n\n".join([d.page_content for d in docs])
|
592 |
+
domain_prompt = ResearchConfig.DOMAIN_PROMPTS.get(domain, "")
|
593 |
+
full_prompt = f"{domain_prompt}\n\n" + ResearchConfig.ANALYSIS_TEMPLATE.format(context=docs_text)
|
594 |
+
response = self.processor.process_query(full_prompt)
|
595 |
+
if "error" in response:
|
596 |
+
logger.error("Backend response error during analysis.")
|
597 |
+
return self._error_state(response["error"])
|
598 |
+
logger.info("Content analysis completed.")
|
599 |
+
return {
|
600 |
+
"messages": [AIMessage(content=response.get('choices', [{}])[0].get('message', {}).get('content', ''))],
|
601 |
+
"context": state["context"]
|
602 |
+
}
|
603 |
except Exception as e:
|
604 |
logger.exception("Error during content analysis.")
|
605 |
return self._error_state(f"Analysis Error: {str(e)}")
|
606 |
|
607 |
def validate_output(self, state: AgentState) -> Dict:
|
|
|
|
|
|
|
608 |
try:
|
609 |
analysis = state["messages"][-1].content
|
610 |
validation_prompt = (
|
|
|
622 |
return self._error_state(f"Validation Error: {str(e)}")
|
623 |
|
624 |
def refine_results(self, state: AgentState) -> Dict:
|
|
|
|
|
|
|
|
|
|
|
|
|
625 |
try:
|
626 |
current_count = state["context"].get("refine_count", 0)
|
627 |
state["context"]["refine_count"] = current_count + 1
|
|
|
660 |
return self._error_state(f"Refinement Error: {str(e)}")
|
661 |
|
662 |
def _quality_check(self, state: AgentState) -> str:
|
|
|
|
|
|
|
|
|
663 |
refine_count = state["context"].get("refine_count", 0)
|
664 |
if refine_count >= 3:
|
665 |
+
logger.warning("Refinement limit reached. Forcing valid outcome.")
|
666 |
return "valid"
|
667 |
content = state["messages"][-1].content
|
668 |
quality = "valid" if "VALID" in content else "invalid"
|
|
|
670 |
return quality
|
671 |
|
672 |
def _error_state(self, message: str) -> Dict:
|
|
|
|
|
|
|
673 |
logger.error(message)
|
674 |
return {
|
675 |
"messages": [AIMessage(content=f"❌ {message}")],
|
|
|
685 |
try:
|
686 |
analysis = state["messages"][-1].content
|
687 |
enhanced = f"{analysis}\n\n## Multi-Modal Insights\n"
|
|
|
688 |
if "images" in state["context"]:
|
689 |
enhanced += "### Visual Evidence\n"
|
690 |
for img in state["context"]["images"]:
|
691 |
enhanced += f"\n"
|
|
|
692 |
if "code" in state["context"]:
|
693 |
enhanced += "### Code Artifacts\n```python\n"
|
694 |
for code in state["context"]["code"]:
|
|
|
703 |
return self._error_state(f"Enhancement Error: {str(e)}")
|
704 |
|
705 |
# ------------------------------
|
706 |
+
# Streamlit Research Interface
|
707 |
# ------------------------------
|
708 |
class ResearchInterface:
|
709 |
"""
|
710 |
Provides the Streamlit-based interface for executing the research workflow.
|
|
|
711 |
"""
|
712 |
def __init__(self) -> None:
|
713 |
self.workflow = ResearchWorkflow()
|
|
|
788 |
|
789 |
def _build_main_interface(self) -> None:
|
790 |
st.title("🧠 NeuroResearch AI")
|
791 |
+
query = st.text_area("Research Query:", height=200, placeholder="Enter technical research question...")
|
|
|
|
|
|
|
|
|
792 |
domain = st.selectbox(
|
793 |
"Select Research Domain:",
|
794 |
options=[
|
|
|
806 |
def _execute_analysis(self, query: str, domain: str) -> None:
|
807 |
try:
|
808 |
with st.spinner("Initializing Quantum Analysis..."):
|
809 |
+
results = self.workflow.app.stream(
|
810 |
+
{
|
811 |
+
"messages": [HumanMessage(content=query)],
|
812 |
+
"context": {"domain": domain},
|
813 |
+
"metadata": {}
|
814 |
+
},
|
815 |
+
{"recursion_limit": 100}
|
816 |
+
)
|
817 |
for event in results:
|
818 |
self._render_event(event)
|
819 |
st.success("✅ Analysis Completed Successfully")
|
|
|
863 |
st.markdown(content)
|
864 |
|
865 |
def _display_knowledge_graph(self) -> None:
|
866 |
+
# Placeholder for knowledge graph visualization
|
867 |
+
st.write("Knowledge Graph visualization is not implemented yet.")
|
868 |
|
869 |
# ------------------------------
|
870 |
# Multi-Modal Retriever Initialization
|