<!-- <p align="center">
<img src="https://raw.githubusercontent.com/superpandas-ai/sagely/main/assets/banner.png" alt="sagely Agent Banner" width="100%" />
</p> -->
<p align="center">
<b>LLM-powered assistant for every Python package!</b><br/>
Just add <code>.sage.ask("your question")</code> to talk to any module.
</p>
<p align="center">
<a href="https://pypi.org/project/sagely/">
<img src="https://img.shields.io/pypi/v/sagely.svg?color=blue" alt="PyPI version">
</a>
<!-- <a href="https://github.com/superpandas-ai/sagely/actions">
<img src="https://github.com/superpandas-ai/sagely/workflows/Tests/badge.svg" alt="CI Status">
</a> -->
<a href="https://github.com/superpandas-ai/sagely">
<img src="https://img.shields.io/github/stars/superpandas-ai/sagely?style=social" alt="GitHub stars">
</a>
</p>
---
# ๐ง Sagely Agent
Sagely Agent automatically injects a `.sage` assistant into every package you import. Ask questions about the library you're using, get help with errors, and explore code with syntax-highlighted answers โ all powered by an LLM.
---
## ๐ฅ Demo (TODO!)
> _(Click to view full video)_
https://github.com/superpandas-ai/sagely/assets/demo.gif
_or_
https://loom.com/share/sagely-demo-link
---
## โ Why Sagely?
There are thousands of Python libraries, but their docs aren't always intuitive. Moreover, getting help about errors or finding usage requires (atleast) asking an LLM manually. With sagely, you can do all that right from the REPL or the jupyter notebook:
- You don't need to search Stack Overflow, or ask ChatGPT, every time you forget a method or run into an error.
- You get context-aware help, including recent exceptions and object summaries.
- It's built for exploration โ whether you're using a notebook, or REPL.
---
## โจ Features
- ๐ง Ask any module `.sage.ask("How do I do X?")` (prints the answer)
- ๐ก Smart context: recent errors + object summaries
- ๐งฉ Auto-attaches to every import
- ๐พ Caches answers to avoid repeated API calls
- ๐ฆ Caches module analysis for faster subsequent queries
- ๐จ Syntax-highlighted output with `rich`
- ๐ง IPython magic: `%sagely pandas how to merge?`
- ๐ **Real-time status updates** showing agent flow progress
- ๐ **Web search integration** with multiple providers (OpenAI web-search, Tavily)
- ๐ **LangSmith tracing** for debugging and monitoring
- โ๏ธ **Centralized configuration system** for customizing agent behavior
- ๐๏ธ **Direct configuration access** via `sagely.config.attribute = value`
- ๐ **Configurable line numbers** in console display
- ๐ฐ **Token usage tracking** with model-specific breakdowns and persistent storage
- ๐ **Usage analytics** with session management and historical data
- ๐ **Real-time usage display** in status updates
---
## ๐ Getting Started
### 1. Install
```bash
pip install sagely
```
### 2. Set up OpenAI API Key
```bash
export OPENAI_API_KEY='your-api-key-here'
```
> **Note**: Sagely currently uses OpenAI's models (gpt-4.1-mini by default), so you must have your OpenAI API key set in the environment. Later we plan to introduce other LLM providers.
### 3. Import It
```python
import sagely
```
It hooks into all future module imports.
## ๐งช Usage Examples
### Inline Python
```python
import matplotlib
matplotlib.sage.ask("how to make a scatter plot?") # This will print the answer
```
### In Jupyter / IPython
```python
%load_ext sagely
%sagely numpy how to generate random numbers?
```
### Programmatic
```python
from sagely import agent
agent.ask("requests", "how do I send a POST request?") # Prints the answer
```
### Status Outputs
The agent provides real-time feedback about what it's doing:
```
โน๏ธ Processing question about 'requests': How do I send a POST request?...
โน๏ธ Starting LangGraph workflow execution...
โน๏ธ Starting context analysis for module: requests
โน๏ธ Analyzing module 'requests'...
โ
Successfully analyzed module 'requests'
โ
Context analysis completed
๐ค Generating initial response...
โ
Initial response generated
๐ค Evaluating if web search is needed...
๐ Web search needed for comprehensive answer
๐ Starting web search for additional information...
๐ Web search 1/3: requests python How do I send a POST request?...
๐ Web search 2/3: requests documentation How do I send a POST request?...
๐ Web search 3/3: python requests best practices How do I send a POST request?...
โ
Web search completed with results
๐ค Generating final response with web search results...
โ
Final response generated successfully
๐ฆ Answer cached for future use
โ
Displaying final answer
```
### โ๏ธ Configuration System
Sagely provides a centralized configuration system for customizing agent behavior, model selection, cache management, and more.
#### Direct Configuration Access (Recommended)
The easiest way to configure Sagely is through direct attribute assignment:
```python
import sagely
# Direct configuration updates
sagely.config.enable_module_cache = False
sagely.config.show_line_numbers = False
sagely.config.model_name = "gpt-3.5-turbo"
sagely.config.web_search_provider = "tavily"
sagely.config.show_status_updates = False
# Changes take effect immediately and affect all future operations
```
#### Programmatic Configuration
```python
from sagely import get_config, update_config, clear_caches, clear_module_cache, reset_config, SageAgent
# View current configuration
config = get_config()
print(config.to_dict())
# Update configuration (e.g., change model, disable status updates)
update_config(model_name="gpt-3.5-turbo", show_status_updates=False)
# Create a new agent with the updated model
agent = SageAgent(model_name=get_config().model_name)
# Reset configuration to defaults
reset_config()
```
#### Available Configuration Options
- `model_name`: LLM model to use (default: "gpt-4.1-mini")
- `show_status_updates`: Show status outputs (default: True)
- `show_line_numbers`: Show line numbers in console display (default: True)
- `enable_response_cache`: Enable/disable response caching (default: True)
- `enable_module_cache`: Enable/disable module info caching (default: True)
- `enable_web_search`: Enable/disable web search (default: True)
- `web_search_provider`: Web search provider ("openai_websearch" or "tavily", default: "openai_websearch")
- `web_search_timeout`: Timeout for web search requests (default: 10)
- `enable_langsmith_tracing`: Enable LangSmith tracing (default: False)
- `langsmith_project`: LangSmith project name (default: None)
#### Cache Management
Sagely uses two types of caches to improve performance:
1. **Response Cache**: Stores answers to questions to avoid repeated API calls
2. **Module Cache**: Stores analyzed module information for faster subsequent queries
To manage caches, import the cache functions:
```python
from sagely import clear_caches, clear_module_cache
# Clear all caches
clear_caches()
# Clear only response cache
clear_caches("response")
# Clear only module cache
clear_caches("module")
# Clear module cache for a specific module
clear_module_cache("json")
# Clear module cache for all modules
clear_module_cache()
```
#### Environment Variable Configuration
You can also configure Sagely using environment variables:
- `SAGELY_MODEL`
- `SAGELY_SHOW_STATUS`
- `SAGELY_SHOW_LINE_NUMBERS`
- `SAGELY_ENABLE_RESPONSE_CACHE`
- `SAGELY_ENABLE_MODULE_CACHE`
- `SAGELY_ENABLE_WEB_SEARCH`
- `SAGELY_WEB_SEARCH_PROVIDER`
- `SAGELY_WEB_SEARCH_TIMEOUT`
- `SAGELY_ENABLE_LANGSMITH`
- `SAGELY_LANGSMITH_PROJECT`
- `TAVILY_API_KEY` (for Tavily web search)
- `OPENAI_API_KEY`
Example:
```bash
export SAGELY_MODEL=gpt-4.1-mini
export SAGELY_SHOW_STATUS=false
export SAGELY_SHOW_LINE_NUMBERS=false
export SAGELY_ENABLE_WEB_SEARCH=true
export SAGELY_WEB_SEARCH_PROVIDER=tavily
export SAGELY_WEB_SEARCH_TIMEOUT=15
export TAVILY_API_KEY=your-tavily-api-key
```
#### Web Search Providers
Sagely supports multiple web search providers for up-to-date information:
**OpenAI Web Search (Default)**
- Uses OpenAI's built-in web search tool
- No additional API key required (uses your OpenAI API key)
- Set with: `sagely.config.web_search_provider = "openai_websearch"`
**Tavily Search**
- Uses Tavily's search API for comprehensive web results
- Requires a Tavily API key: `export TAVILY_API_KEY=your-key`
- Set with: `sagely.config.web_search_provider = "tavily"`
The agent automatically rebuilds its workflow when you change the web search provider.
#### Configuration Persistence
Sagely automatically creates a configuration file at `~/.sagely/config.json` on first run with default settings. You can:
```python
# Save current configuration to file
from sagely.config import save_config
save_config()
# Load configuration from file
from sagely.config import load_config
load_config()
# Or use the global functions
from sagely import save_config, load_config
save_config()
load_config()
```
The configuration file is automatically created with default settings if it doesn't exist.
### ๐ LangSmith Tracing
Sagely supports [LangSmith](https://smith.langchain.com/) for tracing and experiment tracking. To enable LangSmith tracing:
1. **Install dependencies** (already included):
- `langsmith`
- `langchain-core`
2. **Set environment variables** (in your shell or `.env` file):
```sh
export LANGCHAIN_TRACING_V2=true
export LANGCHAIN_API_KEY=your-langsmith-api-key
export LANGCHAIN_PROJECT=your-project-name # optional
```
3. **Enable tracing in configuration**:
```python
import sagely
sagely.config.enable_langsmith_tracing = True
sagely.config.langsmith_project = "my-sagely-project" # optional
```
4. **Run your code as usual**. All LangChain and LangGraph runs will be traced to your LangSmith dashboard.
For more details, see the [LangSmith docs](https://docs.smith.langchain.com/docs/tracing/).
### ๐ง Direct Tool Access
You can access the built-in tools directly for custom implementations:
```python
from sagely.langgraph_agent import analyze_module, get_error_context, web_search
# Analyze a module with comprehensive information
module_info = analyze_module.invoke({"module_name": "json"})
print(module_info)
# Output includes: documentation, functions with docstrings, classes, and submodules
# Get error context
error_info = get_error_context.invoke({})
print(error_info)
# Search the web
web_result = web_search.invoke({"query": "python pandas performance optimization"})
print(web_result)
```
### ๐ Prompt Customization
All prompts are available in the `sagely.prompts` module for customization:
```python
from sagely.prompts import (
INITIAL_RESPONSE_PROMPT,
ORCHESTRATOR_EVALUATION_PROMPT,
FINAL_RESPONSE_WITH_WEB_PROMPT,
FINAL_RESPONSE_WITHOUT_WEB_PROMPT,
SYSTEM_MESSAGE_TEMPLATE
)
# Use prompts for custom implementations
system_msg = SYSTEM_MESSAGE_TEMPLATE.format(module_name="numpy")
initial_prompt = INITIAL_RESPONSE_PROMPT.format(
traceback="No errors",
context_summary="Working with arrays",
module_info="NumPy module info",
question="How to create arrays?"
)
```
## ๐ Token Usage Tracking
Sagely provides comprehensive token usage tracking to help you monitor your API costs and usage patterns. The system automatically tracks all LLM requests and stores detailed usage data both in-memory and in persistent JSON files.
### ๐ฏ Key Features
- **Automatic Tracking**: All LLM requests are automatically tracked
- **Model-Specific Tracking**: Usage is tracked separately for each LLM model
- **Real-Time Display**: Token usage is shown in status updates when enabled
- **Persistent Storage**: Usage data is saved to JSON files in `~/.sagely/usage_data/`
- **Session Management**: Each session gets a unique file with timestamp
- **Historical Analysis**: Access to all previous session data
- **Easy Integration**: Ready for Streamlit app integration
### ๐ Quick Start
```python
import sagely
# Check current session usage
print(f"Total tokens used: {sagely.usage_data.total_tokens:,}")
print(f"Session ID: {sagely.usage_data.session_id}")
# Make some requests (usage is tracked automatically)
import requests
requests.sage.ask("How do I send a POST request?")
# Check updated usage
print(f"Updated tokens: {sagely.usage_data.total_tokens:,}")
```
### ๐ Usage Data Access
#### Via `sagely.usage_data` (Recommended)
The easiest way to access usage information:
```python
import sagely
# Basic usage information
print(f"Input tokens: {sagely.usage_data.input_tokens:,}")
print(f"Output tokens: {sagely.usage_data.output_tokens:,}")
print(f"Total tokens: {sagely.usage_data.total_tokens:,}")
print(f"Request count: {sagely.usage_data.request_count}")
# Session information
print(f"Session ID: {sagely.usage_data.session_id}")
print(f"File path: {sagely.usage_data.session_file_path}")
# Model-specific usage
for model_name, usage in sagely.usage_data.models.items():
print(f"{model_name}: {usage.total_tokens:,} tokens")
# Get usage for specific model
gpt4_usage = sagely.usage_data.get_model_usage("gpt-4")
print(f"gpt-4 usage: {gpt4_usage.total_tokens:,} tokens")
# Get recent usage for a model
recent = sagely.usage_data.get_model_recent_usage("gpt-4o", 3)
for usage in recent:
print(f"{usage.total_tokens} tokens ({usage.request_type})")
# Comprehensive summary
print(sagely.usage_data.summary)
```
#### Via Functions
```python
from sagely import (
get_session_total,
get_session_summary,
get_model_usage,
get_all_model_usage,
get_session_id,
get_session_file_path
)
# Get total usage
total = get_session_total()
print(f"Total: {total.total_tokens:,} tokens")
# Get formatted summary
print(get_session_summary())
# Get model-specific usage
gpt4_usage = get_model_usage("gpt-4")
print(f"gpt-4: {gpt4_usage.total_tokens:,} tokens")
# Get all models
all_models = get_all_model_usage()
for model_name, usage in all_models.items():
print(f"{model_name}: {usage.total_tokens:,} tokens")
```
### ๐พ File-Based Storage
Usage data is automatically saved to JSON files in `~/.sagely/usage_data/` with the following structure:
```
~/.sagely/
โโโ config.json
โโโ usage_data/
โโโ usage_20250709_000629.json
โโโ usage_20250709_000607.json
โโโ usage_20250709_000557.json
โโโ ...
```
#### File Naming Convention
Files are named `usage_YYYYMMDD_HHMMSS.json` where:
- `YYYYMMDD` = Date (Year-Month-Day)
- `HHMMSS` = Time (Hour-Minute-Second)
This ensures no data overwrites and provides chronological ordering.
#### JSON Structure
```json
{
"session_id": "20250709_000629",
"session_start": "2025-07-09T00:06:29.375616",
"usage_history": [
{
"input_tokens": 150,
"output_tokens": 75,
"total_tokens": 225,
"timestamp": "2025-07-09T00:06:29.375696",
"model_name": "gpt-4",
"request_type": "initial_response"
}
],
"model_usage": {
"gpt-4": {
"input_tokens": 250,
"output_tokens": 125,
"total_tokens": 375,
"timestamp": "2025-07-09T00:06:29.375700",
"model_name": "gpt-4",
"request_type": ""
}
}
}
```
### ๐ Session Management
#### Working with Session Files
```python
from sagely import (
get_all_session_files,
load_session_from_file,
load_latest_session
)
# Get all session files (sorted by date, newest first)
session_files = get_all_session_files()
for file_path in session_files[:5]: # Show first 5
print(f"Session: {file_path.name}")
# Load specific session
loaded_tracker = load_session_from_file(session_files[0])
print(f"Loaded tokens: {loaded_tracker.get_session_total().total_tokens:,}")
# Load latest session
latest = load_latest_session()
print(f"Latest session: {latest.get_session_id()}")
```
#### Session Summary Example
```
Session Token Usage:
Total input tokens: 1,234
Total output tokens: 567
Total tokens: 1,801
Session duration: 0:05:30
Total requests: 5
Model Breakdown:
gpt-4:
Input tokens: 800
Output tokens: 400
Total tokens: 1,200
Requests: 3
gpt-4o:
Input tokens: 434
Output tokens: 167
Total tokens: 601
Requests: 2
```
### ๐ Usage Management
#### Clearing Usage Data
```python
from sagely import clear_usage_history, clear_model_history
# Clear all usage history
clear_usage_history()
# Clear history for specific model
clear_model_history("gpt-3.5-turbo")
```
#### Real-Time Status Updates
When `show_status_updates` is enabled, you'll see token usage in real-time:
```
๐ฐ Tokens used: 150 input, 75 output, 225 total
๐ฐ Tokens used: 200 input, 100 output, 300 total
๐ฐ Tokens used: 100 input, 50 output, 150 total
```
### ๐๏ธ Configuration
Token usage tracking can be configured through the main configuration system:
```python
import sagely
# Enable/disable status updates (affects usage display)
sagely.config.show_status_updates = True
# The usage tracking itself is always enabled for data collection
# Status updates only control the display of usage information
```
### ๐ฑ Streamlit Integration
The file-based storage system is designed for easy integration with Streamlit apps:
- **JSON Format**: Easy to parse and analyze
- **Historical Data**: Access to all previous sessions
- **Model Breakdown**: Detailed model-specific usage
- **Timestamp Data**: Precise timing information
- **Session Recovery**: Load any previous session
Example Streamlit data loading:
```python
import streamlit as st
import json
from pathlib import Path
# Load all session files
usage_dir = Path.home() / ".sagely" / "usage_data"
session_files = sorted(usage_dir.glob("usage_*.json"), reverse=True)
# Load and analyze data
for file_path in session_files:
with open(file_path, 'r') as f:
data = json.load(f)
st.write(f"Session: {data['session_id']}")
st.write(f"Total tokens: {sum(usage['total_tokens'] for usage in data['usage_history'])}")
```
### ๐ Advanced Usage
#### Custom Usage Analysis
```python
from sagely import get_usage_tracker
# Get the usage tracker for advanced operations
tracker = get_usage_tracker()
# Get recent usage for specific model
recent_gpt4 = tracker.get_model_recent_usage("gpt-4", 10)
# Analyze usage patterns
for usage in recent_gpt4:
print(f"{usage.timestamp}: {usage.total_tokens} tokens ({usage.request_type})")
```
#### Usage Statistics
```python
import sagely
# Quick usage check
if sagely.usage_data.total_tokens > 0:
print(f"โ
Session active with {sagely.usage_data.total_tokens:,} tokens")
else:
print("โน๏ธ No tokens used yet")
# Model comparison
models = sagely.usage_data.models
if len(models) > 1:
print("๐ Model usage comparison:")
for model_name, usage in models.items():
print(f" {model_name}: {usage.total_tokens:,} tokens")
```
## ๐ง Requirements
- OpenAI API key (set as `OPENAI_API_KEY` environment variable)
- Tavily API key (optional, for Tavily web search provider)
- LangSmith API key (optional, for tracing)
### Dependencies
- openai
- ipywidgets
- rich
- ipython
- langgraph
- langchain-openai
- langchain-tavily (for Tavily web search)
- langchain-core
- requests
- langsmith (optional, for tracing)
(All dependencies are installed automatically.)
## ๐ง Project Structure
```text
sagely/
โโโ src/sagely/
โ โโโ langgraph_agent.py # Main LangGraph-based agent
โ โโโ sage_agent.py # High-level agent interface
โ โโโ cache.py # Caching system
โ โโโ context.py # Context gathering
โ โโโ import_hook.py # Import hooking
โ โโโ ipython_magics.py # IPython magic commands
โ โโโ prompts.py # Prompt templates
โ โโโ tracing.py # LangSmith tracing
โ โโโ widgets.py # Display utilities
โ โโโ config.py # Centralized configuration system
โ โโโ usage_info.py # Token usage tracking system
โ โโโ __init__.py
โโโ tests/
โโโ examples/ # Usage examples in Jupyter notebooks
โโโ pyproject.toml
โโโ MANIFEST.in
โโโ README.md
```
### ๐ Data Storage
```text
~/.sagely/
โโโ config.json # Configuration file
โโโ usage_data/ # Token usage data
โโโ usage_20250709_000629.json
โโโ usage_20250709_000607.json
โโโ ...
```
## ๐ค Contributing
Sagely is early-stage โ PRs and ideas welcome! ๐ฅ
We use [Featurebase](https://sagely.featurebase.app/) for product roadmap and feature requests/tracking
### ๐ Future Features
- Support for other LLM Providers
- Advanced caching and error tracing
- Auto-annotation of cells with answers
- Better prompts and prompt management
- Async & Parallel Context Gathering
- Streaming Response for Jupyter/REPL
- Improved context for large modules using RAG/Summarization/Selective filtering
- Enhanced web search capabilities
- Custom agent workflows
- Integration with more development tools
## ๐งท License
MIT ยฉ 2025 SuperPandas Ltd
Raw data
{
"_id": null,
"home_page": null,
"name": "sagely",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "llm, ai, assistant, repl, jupyter, ipython, documentation",
"author": null,
"author_email": "SuperPandas Ltd <sagely@superpandas.ai>",
"download_url": "https://files.pythonhosted.org/packages/02/7b/9384aa5f6c8619c18f2e9c9a95156e37e3c6cefe0a68b2ffa2b734ea2c4f/sagely-0.1.1.tar.gz",
"platform": null,
"description": "<!-- <p align=\"center\">\n <img src=\"https://raw.githubusercontent.com/superpandas-ai/sagely/main/assets/banner.png\" alt=\"sagely Agent Banner\" width=\"100%\" />\n</p> -->\n\n<p align=\"center\">\n <b>LLM-powered assistant for every Python package!</b><br/>\n Just add <code>.sage.ask(\"your question\")</code> to talk to any module.\n</p>\n\n<p align=\"center\">\n <a href=\"https://pypi.org/project/sagely/\">\n <img src=\"https://img.shields.io/pypi/v/sagely.svg?color=blue\" alt=\"PyPI version\">\n </a>\n <!-- <a href=\"https://github.com/superpandas-ai/sagely/actions\">\n <img src=\"https://github.com/superpandas-ai/sagely/workflows/Tests/badge.svg\" alt=\"CI Status\">\n </a> -->\n <a href=\"https://github.com/superpandas-ai/sagely\">\n <img src=\"https://img.shields.io/github/stars/superpandas-ai/sagely?style=social\" alt=\"GitHub stars\">\n </a>\n</p>\n\n---\n\n# \ud83e\udde0 Sagely Agent\n\nSagely Agent automatically injects a `.sage` assistant into every package you import. Ask questions about the library you're using, get help with errors, and explore code with syntax-highlighted answers \u2014 all powered by an LLM.\n\n---\n\n## \ud83c\udfa5 Demo (TODO!)\n\n> _(Click to view full video)_\n\nhttps://github.com/superpandas-ai/sagely/assets/demo.gif \n_or_ \nhttps://loom.com/share/sagely-demo-link\n\n---\n\n## \u2753 Why Sagely?\n\nThere are thousands of Python libraries, but their docs aren't always intuitive. Moreover, getting help about errors or finding usage requires (atleast) asking an LLM manually. With sagely, you can do all that right from the REPL or the jupyter notebook:\n\n- You don't need to search Stack Overflow, or ask ChatGPT, every time you forget a method or run into an error.\n- You get context-aware help, including recent exceptions and object summaries.\n- It's built for exploration \u2014 whether you're using a notebook, or REPL.\n\n---\n\n## \u2728 Features\n\n- \ud83e\udde0 Ask any module `.sage.ask(\"How do I do X?\")` (prints the answer)\n- \ud83d\udca1 Smart context: recent errors + object summaries\n- \ud83e\udde9 Auto-attaches to every import\n- \ud83d\udcbe Caches answers to avoid repeated API calls\n- \ud83d\udce6 Caches module analysis for faster subsequent queries\n- \ud83c\udfa8 Syntax-highlighted output with `rich`\n- \ud83e\udde0 IPython magic: `%sagely pandas how to merge?`\n- \ud83d\udd0d **Real-time status updates** showing agent flow progress\n- \ud83c\udf10 **Web search integration** with multiple providers (OpenAI web-search, Tavily)\n- \ud83d\udcca **LangSmith tracing** for debugging and monitoring\n- \u2699\ufe0f **Centralized configuration system** for customizing agent behavior\n- \ud83c\udf9b\ufe0f **Direct configuration access** via `sagely.config.attribute = value`\n- \ud83d\udcdd **Configurable line numbers** in console display\n- \ud83d\udcb0 **Token usage tracking** with model-specific breakdowns and persistent storage\n- \ud83d\udcc8 **Usage analytics** with session management and historical data\n- \ud83d\udd04 **Real-time usage display** in status updates\n\n---\n\n## \ud83d\ude80 Getting Started\n\n### 1. Install\n\n```bash\npip install sagely\n```\n\n### 2. Set up OpenAI API Key\n```bash\nexport OPENAI_API_KEY='your-api-key-here'\n```\n> **Note**: Sagely currently uses OpenAI's models (gpt-4.1-mini by default), so you must have your OpenAI API key set in the environment. Later we plan to introduce other LLM providers.\n\n### 3. Import It\n```python\nimport sagely\n```\nIt hooks into all future module imports.\n\n## \ud83e\uddea Usage Examples\n### Inline Python\n```python\nimport matplotlib\n\nmatplotlib.sage.ask(\"how to make a scatter plot?\") # This will print the answer\n```\n\n### In Jupyter / IPython\n```python\n%load_ext sagely\n\n%sagely numpy how to generate random numbers?\n```\n\n### Programmatic\n```python\nfrom sagely import agent\n\nagent.ask(\"requests\", \"how do I send a POST request?\") # Prints the answer\n```\n\n### Status Outputs\nThe agent provides real-time feedback about what it's doing:\n\n```\n\u2139\ufe0f Processing question about 'requests': How do I send a POST request?...\n\u2139\ufe0f Starting LangGraph workflow execution...\n\u2139\ufe0f Starting context analysis for module: requests\n\u2139\ufe0f Analyzing module 'requests'...\n\u2705 Successfully analyzed module 'requests'\n\u2705 Context analysis completed\n\ud83e\udd14 Generating initial response...\n\u2705 Initial response generated\n\ud83e\udd14 Evaluating if web search is needed...\n\ud83d\udd0d Web search needed for comprehensive answer\n\ud83d\udd0d Starting web search for additional information...\n\ud83d\udd0d Web search 1/3: requests python How do I send a POST request?...\n\ud83d\udd0d Web search 2/3: requests documentation How do I send a POST request?...\n\ud83d\udd0d Web search 3/3: python requests best practices How do I send a POST request?...\n\u2705 Web search completed with results\n\ud83e\udd14 Generating final response with web search results...\n\u2705 Final response generated successfully\n\ud83d\udce6 Answer cached for future use\n\u2705 Displaying final answer\n```\n\n### \u2699\ufe0f Configuration System\nSagely provides a centralized configuration system for customizing agent behavior, model selection, cache management, and more.\n\n#### Direct Configuration Access (Recommended)\nThe easiest way to configure Sagely is through direct attribute assignment:\n\n```python\nimport sagely\n\n# Direct configuration updates\nsagely.config.enable_module_cache = False\nsagely.config.show_line_numbers = False\nsagely.config.model_name = \"gpt-3.5-turbo\"\nsagely.config.web_search_provider = \"tavily\"\nsagely.config.show_status_updates = False\n\n# Changes take effect immediately and affect all future operations\n```\n\n#### Programmatic Configuration\n```python\nfrom sagely import get_config, update_config, clear_caches, clear_module_cache, reset_config, SageAgent\n\n# View current configuration\nconfig = get_config()\nprint(config.to_dict())\n\n# Update configuration (e.g., change model, disable status updates)\nupdate_config(model_name=\"gpt-3.5-turbo\", show_status_updates=False)\n\n# Create a new agent with the updated model\nagent = SageAgent(model_name=get_config().model_name)\n\n# Reset configuration to defaults\nreset_config()\n```\n\n#### Available Configuration Options\n- `model_name`: LLM model to use (default: \"gpt-4.1-mini\")\n- `show_status_updates`: Show status outputs (default: True)\n- `show_line_numbers`: Show line numbers in console display (default: True)\n- `enable_response_cache`: Enable/disable response caching (default: True)\n- `enable_module_cache`: Enable/disable module info caching (default: True)\n- `enable_web_search`: Enable/disable web search (default: True)\n- `web_search_provider`: Web search provider (\"openai_websearch\" or \"tavily\", default: \"openai_websearch\")\n- `web_search_timeout`: Timeout for web search requests (default: 10)\n- `enable_langsmith_tracing`: Enable LangSmith tracing (default: False)\n- `langsmith_project`: LangSmith project name (default: None)\n\n#### Cache Management\nSagely uses two types of caches to improve performance:\n\n1. **Response Cache**: Stores answers to questions to avoid repeated API calls\n2. **Module Cache**: Stores analyzed module information for faster subsequent queries\n\nTo manage caches, import the cache functions:\n\n```python\nfrom sagely import clear_caches, clear_module_cache\n\n# Clear all caches\nclear_caches()\n\n# Clear only response cache\nclear_caches(\"response\")\n\n# Clear only module cache\nclear_caches(\"module\")\n\n# Clear module cache for a specific module\nclear_module_cache(\"json\")\n\n# Clear module cache for all modules\nclear_module_cache()\n```\n\n#### Environment Variable Configuration\nYou can also configure Sagely using environment variables:\n- `SAGELY_MODEL`\n- `SAGELY_SHOW_STATUS`\n- `SAGELY_SHOW_LINE_NUMBERS`\n- `SAGELY_ENABLE_RESPONSE_CACHE`\n- `SAGELY_ENABLE_MODULE_CACHE`\n- `SAGELY_ENABLE_WEB_SEARCH`\n- `SAGELY_WEB_SEARCH_PROVIDER`\n- `SAGELY_WEB_SEARCH_TIMEOUT`\n- `SAGELY_ENABLE_LANGSMITH`\n- `SAGELY_LANGSMITH_PROJECT`\n- `TAVILY_API_KEY` (for Tavily web search)\n- `OPENAI_API_KEY`\n\nExample:\n```bash\nexport SAGELY_MODEL=gpt-4.1-mini\nexport SAGELY_SHOW_STATUS=false\nexport SAGELY_SHOW_LINE_NUMBERS=false\nexport SAGELY_ENABLE_WEB_SEARCH=true\nexport SAGELY_WEB_SEARCH_PROVIDER=tavily\nexport SAGELY_WEB_SEARCH_TIMEOUT=15\nexport TAVILY_API_KEY=your-tavily-api-key\n```\n\n#### Web Search Providers\nSagely supports multiple web search providers for up-to-date information:\n\n**OpenAI Web Search (Default)**\n- Uses OpenAI's built-in web search tool\n- No additional API key required (uses your OpenAI API key)\n- Set with: `sagely.config.web_search_provider = \"openai_websearch\"`\n\n**Tavily Search**\n- Uses Tavily's search API for comprehensive web results\n- Requires a Tavily API key: `export TAVILY_API_KEY=your-key`\n- Set with: `sagely.config.web_search_provider = \"tavily\"`\n\nThe agent automatically rebuilds its workflow when you change the web search provider.\n\n#### Configuration Persistence\nSagely automatically creates a configuration file at `~/.sagely/config.json` on first run with default settings. You can:\n\n```python\n# Save current configuration to file\nfrom sagely.config import save_config\nsave_config()\n\n# Load configuration from file\nfrom sagely.config import load_config\nload_config()\n\n# Or use the global functions\nfrom sagely import save_config, load_config\nsave_config()\nload_config()\n```\n\nThe configuration file is automatically created with default settings if it doesn't exist.\n\n### \ud83d\udcca LangSmith Tracing\n\nSagely supports [LangSmith](https://smith.langchain.com/) for tracing and experiment tracking. To enable LangSmith tracing:\n\n1. **Install dependencies** (already included):\n - `langsmith`\n - `langchain-core`\n\n2. **Set environment variables** (in your shell or `.env` file):\n ```sh\n export LANGCHAIN_TRACING_V2=true\n export LANGCHAIN_API_KEY=your-langsmith-api-key\n export LANGCHAIN_PROJECT=your-project-name # optional\n ```\n\n3. **Enable tracing in configuration**:\n ```python\n import sagely\n sagely.config.enable_langsmith_tracing = True\n sagely.config.langsmith_project = \"my-sagely-project\" # optional\n ```\n\n4. **Run your code as usual**. All LangChain and LangGraph runs will be traced to your LangSmith dashboard.\n\nFor more details, see the [LangSmith docs](https://docs.smith.langchain.com/docs/tracing/).\n\n### \ud83d\udd27 Direct Tool Access\n\nYou can access the built-in tools directly for custom implementations:\n\n```python\nfrom sagely.langgraph_agent import analyze_module, get_error_context, web_search\n\n# Analyze a module with comprehensive information\nmodule_info = analyze_module.invoke({\"module_name\": \"json\"})\nprint(module_info)\n# Output includes: documentation, functions with docstrings, classes, and submodules\n\n# Get error context\nerror_info = get_error_context.invoke({})\nprint(error_info)\n\n# Search the web\nweb_result = web_search.invoke({\"query\": \"python pandas performance optimization\"})\nprint(web_result)\n```\n\n### \ud83d\udcdd Prompt Customization\n\nAll prompts are available in the `sagely.prompts` module for customization:\n\n```python\nfrom sagely.prompts import (\n INITIAL_RESPONSE_PROMPT,\n ORCHESTRATOR_EVALUATION_PROMPT,\n FINAL_RESPONSE_WITH_WEB_PROMPT,\n FINAL_RESPONSE_WITHOUT_WEB_PROMPT,\n SYSTEM_MESSAGE_TEMPLATE\n)\n\n# Use prompts for custom implementations\nsystem_msg = SYSTEM_MESSAGE_TEMPLATE.format(module_name=\"numpy\")\ninitial_prompt = INITIAL_RESPONSE_PROMPT.format(\n traceback=\"No errors\",\n context_summary=\"Working with arrays\",\n module_info=\"NumPy module info\",\n question=\"How to create arrays?\"\n)\n```\n\n\n## \ud83d\udcca Token Usage Tracking\n\nSagely provides comprehensive token usage tracking to help you monitor your API costs and usage patterns. The system automatically tracks all LLM requests and stores detailed usage data both in-memory and in persistent JSON files.\n\n### \ud83c\udfaf Key Features\n\n- **Automatic Tracking**: All LLM requests are automatically tracked\n- **Model-Specific Tracking**: Usage is tracked separately for each LLM model\n- **Real-Time Display**: Token usage is shown in status updates when enabled\n- **Persistent Storage**: Usage data is saved to JSON files in `~/.sagely/usage_data/`\n- **Session Management**: Each session gets a unique file with timestamp\n- **Historical Analysis**: Access to all previous session data\n- **Easy Integration**: Ready for Streamlit app integration\n\n### \ud83d\ude80 Quick Start\n\n```python\nimport sagely\n\n# Check current session usage\nprint(f\"Total tokens used: {sagely.usage_data.total_tokens:,}\")\nprint(f\"Session ID: {sagely.usage_data.session_id}\")\n\n# Make some requests (usage is tracked automatically)\nimport requests\nrequests.sage.ask(\"How do I send a POST request?\")\n\n# Check updated usage\nprint(f\"Updated tokens: {sagely.usage_data.total_tokens:,}\")\n```\n\n### \ud83d\udcc8 Usage Data Access\n\n#### Via `sagely.usage_data` (Recommended)\nThe easiest way to access usage information:\n\n```python\nimport sagely\n\n# Basic usage information\nprint(f\"Input tokens: {sagely.usage_data.input_tokens:,}\")\nprint(f\"Output tokens: {sagely.usage_data.output_tokens:,}\")\nprint(f\"Total tokens: {sagely.usage_data.total_tokens:,}\")\nprint(f\"Request count: {sagely.usage_data.request_count}\")\n\n# Session information\nprint(f\"Session ID: {sagely.usage_data.session_id}\")\nprint(f\"File path: {sagely.usage_data.session_file_path}\")\n\n# Model-specific usage\nfor model_name, usage in sagely.usage_data.models.items():\n print(f\"{model_name}: {usage.total_tokens:,} tokens\")\n\n# Get usage for specific model\ngpt4_usage = sagely.usage_data.get_model_usage(\"gpt-4\")\nprint(f\"gpt-4 usage: {gpt4_usage.total_tokens:,} tokens\")\n\n# Get recent usage for a model\nrecent = sagely.usage_data.get_model_recent_usage(\"gpt-4o\", 3)\nfor usage in recent:\n print(f\"{usage.total_tokens} tokens ({usage.request_type})\")\n\n# Comprehensive summary\nprint(sagely.usage_data.summary)\n```\n\n#### Via Functions\n```python\nfrom sagely import (\n get_session_total, \n get_session_summary, \n get_model_usage,\n get_all_model_usage,\n get_session_id,\n get_session_file_path\n)\n\n# Get total usage\ntotal = get_session_total()\nprint(f\"Total: {total.total_tokens:,} tokens\")\n\n# Get formatted summary\nprint(get_session_summary())\n\n# Get model-specific usage\ngpt4_usage = get_model_usage(\"gpt-4\")\nprint(f\"gpt-4: {gpt4_usage.total_tokens:,} tokens\")\n\n# Get all models\nall_models = get_all_model_usage()\nfor model_name, usage in all_models.items():\n print(f\"{model_name}: {usage.total_tokens:,} tokens\")\n```\n\n### \ud83d\udcbe File-Based Storage\n\nUsage data is automatically saved to JSON files in `~/.sagely/usage_data/` with the following structure:\n\n```\n~/.sagely/\n\u251c\u2500\u2500 config.json\n\u2514\u2500\u2500 usage_data/\n \u251c\u2500\u2500 usage_20250709_000629.json\n \u251c\u2500\u2500 usage_20250709_000607.json\n \u251c\u2500\u2500 usage_20250709_000557.json\n \u2514\u2500\u2500 ...\n```\n\n#### File Naming Convention\nFiles are named `usage_YYYYMMDD_HHMMSS.json` where:\n- `YYYYMMDD` = Date (Year-Month-Day)\n- `HHMMSS` = Time (Hour-Minute-Second)\n\nThis ensures no data overwrites and provides chronological ordering.\n\n#### JSON Structure\n```json\n{\n \"session_id\": \"20250709_000629\",\n \"session_start\": \"2025-07-09T00:06:29.375616\",\n \"usage_history\": [\n {\n \"input_tokens\": 150,\n \"output_tokens\": 75,\n \"total_tokens\": 225,\n \"timestamp\": \"2025-07-09T00:06:29.375696\",\n \"model_name\": \"gpt-4\",\n \"request_type\": \"initial_response\"\n }\n ],\n \"model_usage\": {\n \"gpt-4\": {\n \"input_tokens\": 250,\n \"output_tokens\": 125,\n \"total_tokens\": 375,\n \"timestamp\": \"2025-07-09T00:06:29.375700\",\n \"model_name\": \"gpt-4\",\n \"request_type\": \"\"\n }\n }\n}\n```\n\n### \ud83d\udcca Session Management\n\n#### Working with Session Files\n```python\nfrom sagely import (\n get_all_session_files,\n load_session_from_file,\n load_latest_session\n)\n\n# Get all session files (sorted by date, newest first)\nsession_files = get_all_session_files()\nfor file_path in session_files[:5]: # Show first 5\n print(f\"Session: {file_path.name}\")\n\n# Load specific session\nloaded_tracker = load_session_from_file(session_files[0])\nprint(f\"Loaded tokens: {loaded_tracker.get_session_total().total_tokens:,}\")\n\n# Load latest session\nlatest = load_latest_session()\nprint(f\"Latest session: {latest.get_session_id()}\")\n```\n\n#### Session Summary Example\n```\nSession Token Usage:\n Total input tokens: 1,234\n Total output tokens: 567\n Total tokens: 1,801\n Session duration: 0:05:30\n Total requests: 5\n\nModel Breakdown:\n gpt-4:\n Input tokens: 800\n Output tokens: 400\n Total tokens: 1,200\n Requests: 3\n gpt-4o:\n Input tokens: 434\n Output tokens: 167\n Total tokens: 601\n Requests: 2\n```\n\n### \ud83d\udd04 Usage Management\n\n#### Clearing Usage Data\n```python\nfrom sagely import clear_usage_history, clear_model_history\n\n# Clear all usage history\nclear_usage_history()\n\n# Clear history for specific model\nclear_model_history(\"gpt-3.5-turbo\")\n```\n\n#### Real-Time Status Updates\nWhen `show_status_updates` is enabled, you'll see token usage in real-time:\n\n```\n\ud83d\udcb0 Tokens used: 150 input, 75 output, 225 total\n\ud83d\udcb0 Tokens used: 200 input, 100 output, 300 total\n\ud83d\udcb0 Tokens used: 100 input, 50 output, 150 total\n```\n\n### \ud83c\udf9b\ufe0f Configuration\n\nToken usage tracking can be configured through the main configuration system:\n\n```python\nimport sagely\n\n# Enable/disable status updates (affects usage display)\nsagely.config.show_status_updates = True\n\n# The usage tracking itself is always enabled for data collection\n# Status updates only control the display of usage information\n```\n\n### \ud83d\udcf1 Streamlit Integration\n\nThe file-based storage system is designed for easy integration with Streamlit apps:\n\n- **JSON Format**: Easy to parse and analyze\n- **Historical Data**: Access to all previous sessions\n- **Model Breakdown**: Detailed model-specific usage\n- **Timestamp Data**: Precise timing information\n- **Session Recovery**: Load any previous session\n\nExample Streamlit data loading:\n```python\nimport streamlit as st\nimport json\nfrom pathlib import Path\n\n# Load all session files\nusage_dir = Path.home() / \".sagely\" / \"usage_data\"\nsession_files = sorted(usage_dir.glob(\"usage_*.json\"), reverse=True)\n\n# Load and analyze data\nfor file_path in session_files:\n with open(file_path, 'r') as f:\n data = json.load(f)\n st.write(f\"Session: {data['session_id']}\")\n st.write(f\"Total tokens: {sum(usage['total_tokens'] for usage in data['usage_history'])}\")\n```\n\n### \ud83d\udd0d Advanced Usage\n\n#### Custom Usage Analysis\n```python\nfrom sagely import get_usage_tracker\n\n# Get the usage tracker for advanced operations\ntracker = get_usage_tracker()\n\n# Get recent usage for specific model\nrecent_gpt4 = tracker.get_model_recent_usage(\"gpt-4\", 10)\n\n# Analyze usage patterns\nfor usage in recent_gpt4:\n print(f\"{usage.timestamp}: {usage.total_tokens} tokens ({usage.request_type})\")\n```\n\n#### Usage Statistics\n```python\nimport sagely\n\n# Quick usage check\nif sagely.usage_data.total_tokens > 0:\n print(f\"\u2705 Session active with {sagely.usage_data.total_tokens:,} tokens\")\nelse:\n print(\"\u2139\ufe0f No tokens used yet\")\n\n# Model comparison\nmodels = sagely.usage_data.models\nif len(models) > 1:\n print(\"\ud83d\udcca Model usage comparison:\")\n for model_name, usage in models.items():\n print(f\" {model_name}: {usage.total_tokens:,} tokens\")\n```\n\n\n## \ud83d\udd27 Requirements\n- OpenAI API key (set as `OPENAI_API_KEY` environment variable)\n- Tavily API key (optional, for Tavily web search provider)\n- LangSmith API key (optional, for tracing)\n\n### Dependencies\n- openai\n- ipywidgets\n- rich\n- ipython\n- langgraph\n- langchain-openai\n- langchain-tavily (for Tavily web search)\n- langchain-core\n- requests\n- langsmith (optional, for tracing)\n\n(All dependencies are installed automatically.)\n\n## \ud83e\udde0 Project Structure\n```text\nsagely/\n\u251c\u2500\u2500 src/sagely/\n\u2502 \u251c\u2500\u2500 langgraph_agent.py # Main LangGraph-based agent\n\u2502 \u251c\u2500\u2500 sage_agent.py # High-level agent interface\n\u2502 \u251c\u2500\u2500 cache.py # Caching system\n\u2502 \u251c\u2500\u2500 context.py # Context gathering\n\u2502 \u251c\u2500\u2500 import_hook.py # Import hooking\n\u2502 \u251c\u2500\u2500 ipython_magics.py # IPython magic commands\n\u2502 \u251c\u2500\u2500 prompts.py # Prompt templates\n\u2502 \u251c\u2500\u2500 tracing.py # LangSmith tracing\n\u2502 \u251c\u2500\u2500 widgets.py # Display utilities\n\u2502 \u251c\u2500\u2500 config.py # Centralized configuration system\n\u2502 \u251c\u2500\u2500 usage_info.py # Token usage tracking system\n\u2502 \u2514\u2500\u2500 __init__.py\n\u251c\u2500\u2500 tests/\n\u251c\u2500\u2500 examples/ # Usage examples in Jupyter notebooks\n\u251c\u2500\u2500 pyproject.toml\n\u251c\u2500\u2500 MANIFEST.in\n\u2514\u2500\u2500 README.md\n```\n\n### \ud83d\udcc1 Data Storage\n```text\n~/.sagely/\n\u251c\u2500\u2500 config.json # Configuration file\n\u2514\u2500\u2500 usage_data/ # Token usage data\n \u251c\u2500\u2500 usage_20250709_000629.json\n \u251c\u2500\u2500 usage_20250709_000607.json\n \u2514\u2500\u2500 ...\n```\n\n## \ud83e\udd1d Contributing\nSagely is early-stage \u2014 PRs and ideas welcome! \ud83d\udca5\n\nWe use [Featurebase](https://sagely.featurebase.app/) for product roadmap and feature requests/tracking\n\n### \ud83d\ude80 Future Features\n- Support for other LLM Providers\n- Advanced caching and error tracing\n- Auto-annotation of cells with answers\n- Better prompts and prompt management\n- Async & Parallel Context Gathering\n- Streaming Response for Jupyter/REPL\n- Improved context for large modules using RAG/Summarization/Selective filtering\n- Enhanced web search capabilities\n- Custom agent workflows\n- Integration with more development tools\n\n## \ud83e\uddf7 License\nMIT \u00a9 2025 SuperPandas Ltd \n",
"bugtrack_url": null,
"license": null,
"summary": "LLM assistant for Python packages in REPLs and notebooks",
"version": "0.1.1",
"project_urls": {
"Documentation": "https://github.com/superpandas-ai/sagely#readme",
"Homepage": "https://github.com/superpandas-ai/sagely",
"Issues": "https://github.com/superpandas-ai/sagely/issues",
"Repository": "https://github.com/superpandas-ai/sagely"
},
"split_keywords": [
"llm",
" ai",
" assistant",
" repl",
" jupyter",
" ipython",
" documentation"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "6d7c849d29906fec78ea9d9266941be692cf2666114dacd7f6ed80536ec4cb7f",
"md5": "b9bf6059fd3d8164b78d9d5116b98d18",
"sha256": "8b2576fa49d8458c5d4953c9b41a9336305c40669501da68a5eb742a44addc59"
},
"downloads": -1,
"filename": "sagely-0.1.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "b9bf6059fd3d8164b78d9d5116b98d18",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 30160,
"upload_time": "2025-07-08T22:37:37",
"upload_time_iso_8601": "2025-07-08T22:37:37.055213Z",
"url": "https://files.pythonhosted.org/packages/6d/7c/849d29906fec78ea9d9266941be692cf2666114dacd7f6ed80536ec4cb7f/sagely-0.1.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "027b9384aa5f6c8619c18f2e9c9a95156e37e3c6cefe0a68b2ffa2b734ea2c4f",
"md5": "a5d8a35c46fffd9c2fb91eb8a7721a05",
"sha256": "ecd53ef14020a4e3878682494c37808273fe84997fa4245a11ff78542b8c4e4f"
},
"downloads": -1,
"filename": "sagely-0.1.1.tar.gz",
"has_sig": false,
"md5_digest": "a5d8a35c46fffd9c2fb91eb8a7721a05",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 47705,
"upload_time": "2025-07-08T22:37:38",
"upload_time_iso_8601": "2025-07-08T22:37:38.227456Z",
"url": "https://files.pythonhosted.org/packages/02/7b/9384aa5f6c8619c18f2e9c9a95156e37e3c6cefe0a68b2ffa2b734ea2c4f/sagely-0.1.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-08 22:37:38",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "superpandas-ai",
"github_project": "sagely#readme",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "sagely"
}