Skip to content
Merged
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
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
OPENAI_API_KEY='sk-proj-'
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
from llama_index.core.tools.tool_spec.base import BaseToolSpec
from llama_index.agent.introspective import ToolInteractiveReflectionAgentWorker, IntrospectiveAgentWorker
from llama_index.core.agent import FunctionCallingAgentWorker # Import OpenAIAgentWorker here
from llama_index.agent.openai import OpenAIAgentWorker
from llama_index.llms.openai import OpenAI
from llama_index.core.llms import ChatMessage, MessageRole
from datetime import datetime
import yfinance as yf
import pandas as pd
from dotenv import load_dotenv, find_dotenv

load_dotenv(find_dotenv())


class StockDataRetrieverTool(BaseToolSpec):
"""Tool for retrieving stock data"""

spec_functions = ['fetch_historical_prices']

def fetch_historical_prices(self, ticker: str, start_date: str,
end_date: str = datetime.today().strftime('%Y-%m-%d')) -> pd.DataFrame:
"""
Retrieves historical stock prices for a given ticker within a date range.

Args:
ticker (str): The stock ticker symbol.
start_date (str): Start date for data in 'YYYY-MM-DD' format.
end_date (str, optional): End date in 'YYYY-MM-DD' format. Defaults to today.

Returns:
pd.DataFrame: DataFrame with stock price data.
"""
return yf.download(tickers=ticker, start=start_date, end=end_date, progress=True)


class FinancialAgentBuilder:
"""Builder for creating an introspective financial agent with reflection capabilities"""

def __init__(self, data_tool: BaseToolSpec):
self.data_tool = data_tool
self.data_tool_list = data_tool.to_tool_list()

def create_introspective_agent(self, verbose: bool = True, include_main_worker: bool = True):
critique_worker = self._build_critique_worker(verbose)
reflection_worker = self._build_reflection_worker(critique_worker, verbose)
main_worker = self._build_main_worker() if include_main_worker else None

introspective_worker = IntrospectiveAgentWorker.from_defaults(
reflective_agent_worker=reflection_worker,
main_agent_worker=main_worker,
verbose=verbose
)

initial_message = [
ChatMessage(
content="You are a financial assistant that helps gather historical prices "
"and provides a summary of the closing price analysis.",
role=MessageRole.SYSTEM,
)
]
return introspective_worker.as_agent(chat_history=initial_message, verbose=verbose)

def _build_critique_worker(self, verbose: bool):
return FunctionCallingAgentWorker.from_tools(
tools=self.data_tool_list,
llm=OpenAI(model="gpt-4o-mini"),
verbose=verbose
)

def _build_reflection_worker(self, critique_worker, verbose: bool):
def stop_critique_on_pass(critique_str: str):
return "[APPROVE]" in critique_str

return ToolInteractiveReflectionAgentWorker.from_defaults(
critique_agent_worker=critique_worker,
critique_template=(
"Please review the retrieval of historical prices with the specified time intervals. "
"Evaluate the price for accuracy, efficiency, and adherence to truth. "
"If everything is correct, write '[APPROVE]'; otherwise, write '[REJECT]'.\n\n{input_str}"
),
stopping_callable=stop_critique_on_pass,
correction_llm=OpenAI(model='gpt-4o'),
verbose=verbose
)

def _build_main_worker(self):
return OpenAIAgentWorker.from_tools(
tools=self.data_tool_list,
llm=OpenAI("gpt-4-turbo"),
verbose=True
)

Original file line number Diff line number Diff line change
@@ -1,23 +1,37 @@
import litserve as lit
from agent_core import StockDataRetrieverTool, FinancialAgentBuilder

# Query example
# query = """I have 10k dollars Now analyze APPL stock and MSFT stock to let me know where to invest
# this money and how many stock will I get it, Give me the last 3 months historical close prices of
# APPL and MSFT. Respond with a comparative summary on closing prices and recommended stock to invest."""


class IntrospectionAgentAPI(lit.LitAPI):
def __init__(self):
pass
# Instantiate tool and agent
self.stock_data_tool = StockDataRetrieverTool()
self.financial_agent_builder = None

def setup(self, device):
pass
self.financial_agent_builder = FinancialAgentBuilder(data_tool=self.stock_data_tool)

def decode_request(self, request, **kwargs):
pass
return request["query"]

def predict(self, x, **kwargs):
pass
introspective_agent = self.financial_agent_builder.create_introspective_agent(verbose=True)
response = introspective_agent.chat(x)
return response

def encode_response(self, output, **kwargs):
pass
return {"agent": output}


if __name__ == "__main__":
api = IntrospectionAgentAPI()
lit.LitServer(lit_api=api, spec=lit.OpenAISpec())
# pass this parameter "spec=lit.OpenAISpec()", if you want to use the API as
# http://localhost:8002/v1/chat/completion
# else http://localhost:8002/predict
server = lit.LitServer(api, accelerator="auto", spec=lit.OpenAISpec())
server.run(port=8002)
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from agent_core import StockDataRetrieverTool, FinancialAgentBuilder

# Instantiate tool and agent
stock_data_tool = StockDataRetrieverTool()
financial_agent_builder = FinancialAgentBuilder(data_tool=stock_data_tool)
introspective_agent = financial_agent_builder.create_introspective_agent(verbose=True)

# Query example
query = """I have 10k dollars Now analyze APPL stock and MSFT stock to let me know where to invest
this money and how many stock will I get it, Give me the last 3 months historical close prices of APPL and MSFT.
Respond with a comparative summary on closing prices and recommended stock to invest."""
response = introspective_agent.chat(query)
print(response)
Original file line number Diff line number Diff line change
@@ -1 +1,20 @@
### under progress
### Introspective Financial Agents

Introspective agents are artificial intelligence systems designed to evaluate and refine their own outputs through iterative reflection and correction. This self-assessment process enables them to improve performance over time. For instance, in the LlamaIndex framework, an introspective agent generates an initial response to a task and then engages in reflection and correction cycles to enhance the response until a satisfactory outcome is achieved.

An introspective worker agent is a specific implementation of this concept. It operates by delegating tasks to two other agents: one generates the initial response, and the other performs reflection and correction on that response. This structured approach ensures systematic evaluation and improvement of outputs.

### How to run ?
- `pip install -r requirements.txt`
- `python main.py` [standalone code]
- `python api_server.py` [litserve apis]

### How to access API?
- URL: http://localhost:8002/predict
- method: POST
- payload:
```json
{
"query": "I have 10k dollars Now analyze APPL stock and MSFT stock to let me know where to invest this money and how many stock will I get it, Give me the last 3 months historical close prices of APPL and MSFT. Respond with a comparative summary on closing prices and recommended stock to invest."
}
```