Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions use-case-examples/Stock Analysis Agent/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
static/
__pycache__/
*.pyc
59 changes: 59 additions & 0 deletions use-case-examples/Stock Analysis Agent/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Stock Analysis Agent

This agent demonstrates how to build an agentic application using Nemotron for financial data analysis. It uses **yfinance** to fetch real-time stock data and **Plotly** for interactive visualizations.

**Key Features:**
- 💰 Get current stock prices
- 🏢 Retrieve company information (sector, industry, business summary)
- 📊 Plot interactive historical price charts with major price movement detection
- 🎯 Simulate "What If?" investment scenarios
- 🔍 Identify significant price spikes and dips automatically

![Stock Analysis Agent Screenshot](screenshot.png)

## Overview

The agent uses the `yfinance` library to fetch market data and `Plotly` to generate charts. It leverages the **Nemotron-Nano-9B-v2** model (or other Nemotron variants) to understand user intent and call the appropriate tools.

## Requirements

- Python 3.10+
- NVIDIA API Key (get one at [build.nvidia.com](https://build.nvidia.com/))

## Installation

1. **Create and activate a virtual environment (Recommended):**
```bash
python3 -m venv venv
source venv/bin/activate
```

2. **Install dependencies:**
```bash
pip install -r requirements.txt
```

3. **Set your NVIDIA API Key:**
```bash
export NVIDIA_API_KEY="nvapi-..."
```

## Usage

Run the Streamlit app:

```bash
streamlit run app.py
```

## Example Queries

Try these questions with the agent:

- "What is the current price of NVDA?"
- "Tell me about Tesla."
- "Plot the 1-year history of Apple."
- "What if I invested $500 in NVDA 1 year ago?"
- "Simulate investing $1000 in Microsoft 2 years ago."
- "Show me the price movements of Google over 6 months."
- "Compare the prices of Google and Amazon."
102 changes: 102 additions & 0 deletions use-case-examples/Stock Analysis Agent/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import streamlit as st
import os
from src.stock_agent import StockAgent

st.set_page_config(page_title="Stock Analysis Agent", page_icon="📈", layout="wide")

# Initialize session state
if "agent" not in st.session_state:
st.session_state.agent = StockAgent()
if "messages" not in st.session_state:
st.session_state.messages = []

# Sidebar
with st.sidebar:
st.header("📈 Stock Agent")
st.markdown("""
This agent uses **NVIDIA Nemotron** to analyze stock market data.

**Capabilities:**
- 💰 Get current stock prices
- 🏢 Get company information
- 📊 Plot historical price charts
- 🎯 Simulate "What If?" investment scenarios

**Example Queries:**
- "What is the price of NVDA?"
- "Tell me about Microsoft."
- "Plot the 1-year history of Apple."
- "What if I invested $500 in NVDA 1 year ago?"
- "Simulate investing $1000 in Tesla 2 years ago."
""")

if st.button("🗑️ Clear Chat"):
st.session_state.messages = []
st.session_state.agent.clear_history()
st.rerun()

# API Key check
if not os.getenv("NVIDIA_API_KEY"):
st.error("⚠️ NVIDIA_API_KEY not found!")
st.info("Please set the environment variable before running.")

# Main Chat Interface
st.title("💬 Stock Analysis Assistant")

# Display messages
for message in st.session_state.messages:
with st.chat_message(message["role"]):
# Check for chart data in the content
content = message["content"]
chart_data = None

if "CHART_DATA:" in content:
# Extract the chart data and clean the content
parts = content.split("CHART_DATA:")
content = parts[0].strip()
if len(parts) > 1:
chart_data = parts[1].strip()

st.markdown(content)

if chart_data:
try:
import plotly.graph_objects as go
import json
fig = go.Figure(json.loads(chart_data))
st.plotly_chart(fig, use_container_width=True)
except Exception:
pass

# User Input
if prompt := st.chat_input("Ask about stocks..."):
# Add user message
st.session_state.messages.append({"role": "user", "content": prompt})
with st.chat_message("user"):
st.markdown(prompt)

# Generate response
with st.chat_message("assistant"):
with st.spinner("Thinking..."):
response, chart_data = st.session_state.agent.chat(prompt)

# Display the text response
st.markdown(response)

# Display the chart if one was generated
if chart_data:
try:
import plotly.graph_objects as go
import json
# Parse the JSON and create figure
fig = go.Figure(json.loads(chart_data))
st.plotly_chart(fig, use_container_width=True)
except Exception as e:
st.error(f"Error displaying chart: {e}")

# Store in session (we'll store chart data separately)
content_to_store = response
if chart_data:
content_to_store += f"\n\nCHART_DATA:{chart_data}"

st.session_state.messages.append({"role": "assistant", "content": content_to_store})
5 changes: 5 additions & 0 deletions use-case-examples/Stock Analysis Agent/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
streamlit
yfinance
plotly
pandas
requests
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
87 changes: 87 additions & 0 deletions use-case-examples/Stock Analysis Agent/src/llm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# llm.py
import os
from typing import List, Optional
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

# Configuration
BASE_URL = os.getenv("NIM_BASE_URL", "https://integrate.api.nvidia.com/v1")
MODEL = os.getenv("NIM_MODEL", "nvidia/nvidia-nemotron-nano-9b-v2")
TEMPERATURE = float(os.getenv("NIM_TEMPERATURE", "0"))
MAX_TOKENS = int(os.getenv("NIM_MAX_TOKENS", "4096"))

# Set up HTTP session with retries
def create_session():
"""Create a session with retry logic for better reliability."""
session = requests.Session()

# Retry Strategy for Resilient Communication
retry_strategy = Retry(
total=3, # Try 3 times
backoff_factor=1, # Wait 1, 2, 4 seconds between retries
status_forcelist=[429, 500, 502, 503, 504], # Retry on these errors
)

adapter = HTTPAdapter(max_retries=retry_strategy)
session.mount("https://", adapter)
session.mount("http://", adapter)

return session

class LLMClient:
"""Simple client to talk to AI models."""

def __init__(self):
# Get API key from environment
self.api_key = os.getenv("NVIDIA_API_KEY")
if not self.api_key:
raise ValueError("Please set NVIDIA_API_KEY environment variable")

self.base_url = BASE_URL.rstrip("/")
self.model = MODEL
self.temperature = TEMPERATURE
self.max_tokens = MAX_TOKENS
self.session = create_session()

def chat(self, messages: List[dict], tools: Optional[List[dict]] = None) -> dict:
"""Send messages to the AI and get a response."""

# Prepare the request
request_data = {
"model": self.model,
"messages": messages,
"temperature": self.temperature,
"max_tokens": self.max_tokens,
}

# Add tools if provided
if tools:
request_data["tools"] = tools
request_data["tool_choice"] = "auto"

# Set up headers
headers = {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"
}

try:
# Make the request
response = self.session.post(
f"{self.base_url}/chat/completions",
headers=headers,
json=request_data,
timeout=(10, 300) # 10 seconds to connect, 300 seconds to read
)

# Check if request was successful
response.raise_for_status()
return response.json()

except requests.exceptions.RequestException as e:
raise RuntimeError(f"Failed to communicate with AI: {e}")

def create_client() -> LLMClient:
"""Create a new LLM client."""
return LLMClient()
Loading