Ai-Research-Assistant / run_cli.py
Ak47-model-ml's picture
Initial commit: AI Research Assistant
c81d06a
Raw
History Blame Contribute Delete
5.56 kB
"""
CLI Runner — test the full pipeline without Gradio.
Usage: python run_cli.py --query "federated learning in healthcare"
"""
import argparse
import json
import logging
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent))
from workflows.langgraph_workflow import run_research_pipeline
from agents.llm_helper import check_ollama_available
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s | %(levelname)s | %(message)s",
datefmt="%H:%M:%S")
def main():
parser = argparse.ArgumentParser(
description="AI Research Assistant CLI",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
python run_cli.py --query "federated learning in healthcare"
python run_cli.py --query "LLMs for EHR analysis" --year 2022 --max-papers 15
python run_cli.py --query "medical imaging segmentation" --no-surveys --output results.json
"""
)
parser.add_argument("--query", required=True, help="Research query")
parser.add_argument("--year", type=int, default=0, help="Filter papers after this year")
parser.add_argument("--max-papers", type=int, default=20, help="Max papers to retrieve")
parser.add_argument("--no-surveys", action="store_true", help="Exclude survey/review papers")
parser.add_argument("--output", default="", help="Save results to JSON file")
parser.add_argument("--verbose", action="store_true", help="Show debug logs")
args = parser.parse_args()
if args.verbose:
logging.getLogger().setLevel(logging.DEBUG)
if not check_ollama_available():
print("\n⚠️ WARNING: Ollama is not running. LLM features will be degraded.")
print(" Install: curl https://ollama.ai/install.sh | sh")
print(" Pull: ollama pull phi3:mini")
print(" Start: ollama serve\n")
filters = {"max_papers": args.max_papers}
if args.year > 2000:
filters["year_after"] = args.year
if args.no_surveys:
filters["exclude_surveys"] = True
print(f"\n{'='*60}")
print(f" AI Research Assistant — CLI")
print(f"{'='*60}")
print(f" Query: {args.query}")
print(f" Filters: {filters}")
print(f"{'='*60}\n")
state = run_research_pipeline(query=args.query, filters=filters)
ranked = state.get("ranked_papers", [])
metrics = state.get("metrics", {})
insights = state.get("insights", {})
errors = state.get("errors", [])
print(f"\n{'='*60}")
print(f" RESULTS")
print(f"{'='*60}")
print(f" Papers retrieved: {metrics.get('papers_retrieved', 0)}")
print(f" Papers ranked: {len(ranked)}")
print(f" Mean score: {metrics.get('score_mean', 0):.3f}")
print(f" Std deviation: {metrics.get('score_std', 0):.3f}")
print(f" Pipeline time: {metrics.get('query_time_sec', 0):.1f}s")
if errors:
print(f"\n ⚠️ Errors ({len(errors)}):")
for e in errors:
print(f" - {e}")
if ranked:
print(f"\n Top 5 Papers:")
print(f" {'─'*55}")
for i, p in enumerate(ranked[:5], 1):
print(f" {i}. [{p['final_score']:.3f}] {p['title'][:65]}")
print(f" Year: {p.get('published','')[:4]} | "
f"Citations: {p.get('citation_count', 0)} | "
f"Venue: {p.get('venue', 'arXiv')[:25]}")
sb = p.get("score_breakdown", {})
print(f" Scores → "
f"Citation:{sb.get('citation_score',0):.2f} "
f"Recency:{sb.get('recency_score',0):.2f} "
f"Venue:{sb.get('venue_score',0):.2f} "
f"LLM:{sb.get('llm_quality_score',0):.2f}")
subtopics = state.get("subtopics", [])
if subtopics:
print(f"\n Subtopics identified:")
for t in subtopics:
print(f" • {t}")
if insights.get("research_gaps"):
print(f"\n Research Gaps:")
for line in insights["research_gaps"].split("\n")[:5]:
clean = line.strip().lstrip("•-*0123456789.)> ").strip()
if clean:
print(f" • {clean}")
if insights.get("future_directions"):
print(f"\n Future Directions:")
for line in insights["future_directions"].split("\n")[:4]:
clean = line.strip().lstrip("•-*0123456789.)> ").strip()
if clean:
print(f" → {clean}")
if args.output:
output_data = {
"query": args.query,
"filters": filters,
"metrics": metrics,
"subtopics": state.get("subtopics", []),
"ranked_papers": [
{k: v for k, v in p.items() if k != "abstract"}
for p in ranked[:20]
],
"insights": insights,
"knowledge_graph": {
"entities": state.get("knowledge_graph_entities", []),
"edges": state.get("knowledge_graph_edges", [])
}
}
with open(args.output, "w") as f:
json.dump(output_data, f, indent=2)
print(f"\n ✅ Results saved to: {args.output}")
artifacts = state.get("artifacts", {})
print(f"\n Generated Artifacts:")
for atype in ["report", "bibtex", "related_work"]:
if artifacts.get(atype):
print(f" ✓ {atype}")
print(f" Location: data/artifacts/")
print(f"{'='*60}\n")
if __name__ == "__main__":
main()