Spaces:
Sleeping
Sleeping
| import json | |
| from typing import Any, Dict, Optional | |
| from langchain_core.tools import tool | |
| from langgraph.prebuilt import create_react_agent | |
| import tools as pipeline_tools | |
| _AGENT_CONTEXT: Dict[str, Any] = { | |
| "csv_path": None, | |
| "output_dir": ".", | |
| } | |
| def _topic_summary(result: pipeline_tools.AnalysisResult) -> Dict[str, Any]: | |
| table = result.topic_table | |
| top_labels = table.sort_values("Count", ascending=False)["Label"].head(10).tolist() if not table.empty else [] | |
| return { | |
| "source": result.source_column, | |
| "papers": result.paper_count, | |
| "analysis_units": result.unit_count, | |
| "topic_count": int(len(table)), | |
| "top_labels": top_labels, | |
| } | |
| def run_abstract_analysis_tool() -> str: | |
| """Run Braun and Clarke thematic pipeline on the Abstract column.""" | |
| result = pipeline_tools.run_single_analysis( | |
| mode="abstract", | |
| csv_path=_AGENT_CONTEXT.get("csv_path"), | |
| output_dir=_AGENT_CONTEXT.get("output_dir", "."), | |
| ) | |
| payload = { | |
| "status": "ok", | |
| "summary": _topic_summary(result), | |
| } | |
| return json.dumps(payload, indent=2) | |
| def run_title_analysis_tool() -> str: | |
| """Run Braun and Clarke thematic pipeline on the Title column.""" | |
| result = pipeline_tools.run_single_analysis( | |
| mode="title", | |
| csv_path=_AGENT_CONTEXT.get("csv_path"), | |
| output_dir=_AGENT_CONTEXT.get("output_dir", "."), | |
| ) | |
| payload = { | |
| "status": "ok", | |
| "summary": _topic_summary(result), | |
| } | |
| return json.dumps(payload, indent=2) | |
| def run_full_pipeline_tool() -> str: | |
| """Run full end-to-end pipeline for abstract and title, then generate comparison and narrative files.""" | |
| result = pipeline_tools.run_full_pipeline( | |
| csv_path=_AGENT_CONTEXT.get("csv_path"), | |
| output_dir=_AGENT_CONTEXT.get("output_dir", "."), | |
| ) | |
| payload = { | |
| "status": "ok", | |
| "csv_path": result["csv_path"], | |
| "abstract_topics": int(len(result["abstract"].topic_table)), | |
| "title_topics": int(len(result["title"].topic_table)), | |
| "comparison_rows": int(len(result["comparison"])), | |
| "files": result["files"], | |
| } | |
| return json.dumps(payload, indent=2) | |
| def get_output_files_tool() -> str: | |
| """Get generated deliverable file paths.""" | |
| files = pipeline_tools.ensure_output_artifacts(_AGENT_CONTEXT.get("output_dir", ".")) | |
| return json.dumps(files, indent=2) | |
| def _fallback_router(message: str, csv_path: Optional[str], output_dir: str) -> str: | |
| lowered = message.lower() | |
| if "full" in lowered or "end to end" in lowered or "pipeline" in lowered or "compare" in lowered: | |
| result = pipeline_tools.run_full_pipeline(csv_path=csv_path, output_dir=output_dir) | |
| return ( | |
| "Full pipeline complete. " | |
| f"Abstract topics: {len(result['abstract'].topic_table)} | " | |
| f"Title topics: {len(result['title'].topic_table)} | " | |
| f"Comparison rows: {len(result['comparison'])}." | |
| ) | |
| if "abstract" in lowered: | |
| result = pipeline_tools.run_single_analysis(mode="abstract", csv_path=csv_path, output_dir=output_dir) | |
| return ( | |
| "Abstract analysis complete. " | |
| f"Identified {len(result.topic_table)} topics from {result.unit_count} cleaned analysis units." | |
| ) | |
| if "title" in lowered: | |
| result = pipeline_tools.run_single_analysis(mode="title", csv_path=csv_path, output_dir=output_dir) | |
| return ( | |
| "Title analysis complete. " | |
| f"Identified {len(result.topic_table)} topics from {result.unit_count} cleaned analysis units." | |
| ) | |
| files = pipeline_tools.ensure_output_artifacts(output_dir) | |
| return ( | |
| "I can run 'abstract analysis', 'title analysis', or 'full pipeline'. " | |
| f"Current output files are available at: {files}" | |
| ) | |
| def run_agent_command(message: str, csv_path: Optional[str] = None, output_dir: str = ".") -> str: | |
| _AGENT_CONTEXT["csv_path"] = csv_path | |
| _AGENT_CONTEXT["output_dir"] = output_dir | |
| llm = pipeline_tools.create_groq_llm(temperature=0.1) | |
| if llm is None: | |
| return _fallback_router(message, csv_path=csv_path, output_dir=output_dir) | |
| tools = [ | |
| run_abstract_analysis_tool, | |
| run_title_analysis_tool, | |
| run_full_pipeline_tool, | |
| get_output_files_tool, | |
| ] | |
| try: | |
| react_agent = create_react_agent(llm, tools) | |
| response = react_agent.invoke({"messages": [("user", message)]}) | |
| messages = response.get("messages", []) | |
| if not messages: | |
| return _fallback_router(message, csv_path=csv_path, output_dir=output_dir) | |
| final_message = messages[-1] | |
| content = getattr(final_message, "content", str(final_message)) | |
| return str(content) | |
| except Exception: | |
| return _fallback_router(message, csv_path=csv_path, output_dir=output_dir) | |