From ce2cfd2ed5dd0a856276200c22ae3f8135b07922 Mon Sep 17 00:00:00 2001 From: pavanmantha Date: Thu, 21 Nov 2024 22:51:15 +0530 Subject: [PATCH] -introspection agents with observability --- bootstraprag/cli.py | 1 + .../.env | 6 ++ .../__init__.py | 0 .../agent_core.py | 92 +++++++++++++++++++ .../api_server.py | 37 ++++++++ .../docker-compose-langfuse.yml | 36 ++++++++ .../main.py | 13 +++ .../readme.md | 26 ++++++ .../requirements.txt | 12 +++ 9 files changed, 223 insertions(+) create mode 100644 bootstraprag/templates/llamaindex/agents_with_introspection_with_observability/.env create mode 100644 bootstraprag/templates/llamaindex/agents_with_introspection_with_observability/__init__.py create mode 100644 bootstraprag/templates/llamaindex/agents_with_introspection_with_observability/agent_core.py create mode 100644 bootstraprag/templates/llamaindex/agents_with_introspection_with_observability/api_server.py create mode 100644 bootstraprag/templates/llamaindex/agents_with_introspection_with_observability/docker-compose-langfuse.yml create mode 100644 bootstraprag/templates/llamaindex/agents_with_introspection_with_observability/main.py create mode 100644 bootstraprag/templates/llamaindex/agents_with_introspection_with_observability/readme.md create mode 100644 bootstraprag/templates/llamaindex/agents_with_introspection_with_observability/requirements.txt diff --git a/bootstraprag/cli.py b/bootstraprag/cli.py index ba5afe6..32bdaf3 100644 --- a/bootstraprag/cli.py +++ b/bootstraprag/cli.py @@ -37,6 +37,7 @@ def create(project_name, framework, template, observability): 'rag-with-self-correction', 'rag-with-controllable-agents', 'rag-with-llama-parse', + 'agents-with-introspection', 'llama-deploy-with-simplemq', 'llama-deploy-with-rabbitmq', 'llama-deploy-with-kafka' diff --git a/bootstraprag/templates/llamaindex/agents_with_introspection_with_observability/.env b/bootstraprag/templates/llamaindex/agents_with_introspection_with_observability/.env new file mode 100644 index 0000000..67c818c --- /dev/null +++ b/bootstraprag/templates/llamaindex/agents_with_introspection_with_observability/.env @@ -0,0 +1,6 @@ +OPENAI_API_KEY='sk-proj-' + +# Langfuse Observability Details +LANGFUSE_PUBLIC_KEY='pk-lf-0cefdf2d-2d95-4cee-bd3b-cf0f79b8e068' +LANGFUSE_SECRET_KEY='sk-lf-1d56e47f-8d3e-4c22-8be7-5ffdfdc535b7' +LANGFUSE_HOST='http://localhost:3000' \ No newline at end of file diff --git a/bootstraprag/templates/llamaindex/agents_with_introspection_with_observability/__init__.py b/bootstraprag/templates/llamaindex/agents_with_introspection_with_observability/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/bootstraprag/templates/llamaindex/agents_with_introspection_with_observability/agent_core.py b/bootstraprag/templates/llamaindex/agents_with_introspection_with_observability/agent_core.py new file mode 100644 index 0000000..321c25f --- /dev/null +++ b/bootstraprag/templates/llamaindex/agents_with_introspection_with_observability/agent_core.py @@ -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 + ) + diff --git a/bootstraprag/templates/llamaindex/agents_with_introspection_with_observability/api_server.py b/bootstraprag/templates/llamaindex/agents_with_introspection_with_observability/api_server.py new file mode 100644 index 0000000..a4e3d47 --- /dev/null +++ b/bootstraprag/templates/llamaindex/agents_with_introspection_with_observability/api_server.py @@ -0,0 +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): + # Instantiate tool and agent + self.stock_data_tool = StockDataRetrieverTool() + self.financial_agent_builder = None + + def setup(self, device): + self.financial_agent_builder = FinancialAgentBuilder(data_tool=self.stock_data_tool) + + def decode_request(self, request, **kwargs): + return request["query"] + + def predict(self, x, **kwargs): + introspective_agent = self.financial_agent_builder.create_introspective_agent(verbose=True) + response = introspective_agent.chat(x) + return response + + def encode_response(self, output, **kwargs): + return {"agent": output} + + +if __name__ == "__main__": + api = IntrospectionAgentAPI() + # 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) diff --git a/bootstraprag/templates/llamaindex/agents_with_introspection_with_observability/docker-compose-langfuse.yml b/bootstraprag/templates/llamaindex/agents_with_introspection_with_observability/docker-compose-langfuse.yml new file mode 100644 index 0000000..2363657 --- /dev/null +++ b/bootstraprag/templates/llamaindex/agents_with_introspection_with_observability/docker-compose-langfuse.yml @@ -0,0 +1,36 @@ +version: '3.8' + +services: + postgres: + image: postgres:latest + container_name: postgres + environment: + POSTGRES_PASSWORD: postgres + POSTGRES_DB: langfuse + volumes: + - postgres_data:/var/lib/postgresql/data + networks: + - langfuse-network + + langfuse: + image: langfuse/langfuse:latest + container_name: langfuse + environment: + DATABASE_URL: postgresql://postgres:postgres@postgres:5432/langfuse + NEXTAUTH_URL: http://localhost:3000 + NEXTAUTH_SECRET: mysecret + SALT: mysalt + ENCRYPTION_KEY: 98637d42c277ef10b8a324e25d492daa8eee8f769574124ba25132f71481f183 + ports: + - "3000:3000" + depends_on: + - postgres + networks: + - langfuse-network + +volumes: + postgres_data: + +networks: + langfuse-network: + driver: bridge diff --git a/bootstraprag/templates/llamaindex/agents_with_introspection_with_observability/main.py b/bootstraprag/templates/llamaindex/agents_with_introspection_with_observability/main.py new file mode 100644 index 0000000..a92e134 --- /dev/null +++ b/bootstraprag/templates/llamaindex/agents_with_introspection_with_observability/main.py @@ -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) \ No newline at end of file diff --git a/bootstraprag/templates/llamaindex/agents_with_introspection_with_observability/readme.md b/bootstraprag/templates/llamaindex/agents_with_introspection_with_observability/readme.md new file mode 100644 index 0000000..4437003 --- /dev/null +++ b/bootstraprag/templates/llamaindex/agents_with_introspection_with_observability/readme.md @@ -0,0 +1,26 @@ +### 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. + +### Setup Langfuse for observability +- `docker-compose run -f docker-compose-langfuse.yml` + +### 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." +} +``` + +### How to check traces? +launch `http://localhost:3000` diff --git a/bootstraprag/templates/llamaindex/agents_with_introspection_with_observability/requirements.txt b/bootstraprag/templates/llamaindex/agents_with_introspection_with_observability/requirements.txt new file mode 100644 index 0000000..40d38e8 --- /dev/null +++ b/bootstraprag/templates/llamaindex/agents_with_introspection_with_observability/requirements.txt @@ -0,0 +1,12 @@ +llama-index-agent-introspective +llama-index-llms-openai +llama-index-llms-ollama +llama-index-embeddings-ollama +llama-index-vector-stores-qdrant +llama-index-program-openai +llama-index-readers-file +yfinance +pandas +python-dotenv +# observability +langfuse==2.52.2 \ No newline at end of file