├── .DS_Store ├── .gitignore ├── benchmark_stock_analysis ├── .DS_Store ├── agent_zero │ ├── benchmkark.txt │ ├── concept.txt │ ├── prompt.txt │ ├── start_prompt.txt │ └── warren_buffet_investement_principles.txt ├── autogen │ ├── autogen_stock_analysis.py │ ├── benchmark.txt │ ├── concept.txt │ ├── stock_analysis.txt │ ├── tools │ │ ├── __pycache__ │ │ │ └── yahoo_finance.cpython-312.pyc │ │ └── yahoo_finance.py │ └── warren_buffet_investement_principles.txt ├── crewai │ ├── benchmark.txt │ ├── get_stock_news.py │ ├── main.py │ ├── stock_analysis.txt │ ├── stock_summary.txt │ ├── tools │ │ ├── YFinanceNewsTool.py │ │ ├── YFinanceStockAnalysisTool.py │ │ └── __pycache__ │ │ │ ├── YFinanceNewsTool.cpython-312.pyc │ │ │ └── YFinanceStockAnalysisTool.cpython-312.pyc │ └── warren_buffet_investement_principles.txt ├── langraph │ ├── .DS_Store │ ├── benchmark.txt │ ├── concept.txt │ ├── graph_concept.txt │ ├── stock_analysis.py │ ├── stock_analysis.txt │ ├── tools │ │ ├── __pycache__ │ │ │ └── yahoo_finance.cpython-312.pyc │ │ └── yahoo_finance.py │ └── warren_buffet_investement_principles.txt └── summary │ ├── analyse.py │ └── framework_comparison.csv ├── blog_writer.py ├── dev_habit_tracker ├── index.tsx ├── prompt.txt └── views │ ├── CalendarView.tsx │ ├── EditView.tsx │ └── HabitView.tsx ├── lead_scraper ├── autogen │ └── autogen_lead_scraper.py ├── crewai │ └── crewai_lead_scraper.py ├── requirements.txt └── tools │ └── scraper.py ├── meal_planner ├── dish_list.txt ├── last_week_schedule.txt └── main.py ├── readmes └── claude-mcp.md ├── sell_ai_agents └── cost_reduction.pptx ├── structured_data ├── autogen │ └── autogen_structured_output.py ├── crewai │ └── crewai_structured_output.py ├── data │ ├── workflow_metrics_full.csv │ └── workflows_full.csv ├── langchain │ └── langchain_structured_output.py ├── openai_agents │ └── openai_agents_structred_output.py ├── pydantic_agents │ └── pydantic_structured_output.py └── warren_buffet_investement_principles.txt ├── task_delegation.py ├── tools └── tool_yahoo_finance.py ├── webDev ├── constants.py ├── ini_description.txt ├── model_page.png ├── recent_screenshot.png ├── recent_state.html ├── recent_state_analysis.txt ├── utils │ ├── analyse_image.py │ ├── compare_images.py │ └── store_screenshot.py ├── versions │ └── recent_screenshot.png └── web_dev.py ├── youtube_automation ├── .env.demo ├── agents.py ├── main.py ├── tasks.py └── tools │ └── youtube_video_full_search_tool.py └── youtube_insights ├── __pycache__ ├── agents.cpython-312.pyc └── tasks.cpython-312.pyc ├── agents.py ├── main.py ├── tasks.py └── tools ├── __init__.py ├── __pycache__ ├── __init__.cpython-312.pyc ├── youtube_video_details_tool.cpython-312.pyc ├── youtube_video_full_search_tool.cpython-312.pyc ├── youtube_video_search_tool.cpython-312.pyc └── youtuve_video_transcrip_reader_tool.cpython-312.pyc ├── test copy.py ├── test.py ├── youtube_video_full_search_tool.py └── youtuve_video_transcrip_reader_tool.py /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Florenz23/ai-agent-videos/4d06a1d2956ea7f16b8e11074e71f5c16e91f41d/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # Distribution / packaging 7 | dist/ 8 | build/ 9 | *.egg-info/ 10 | 11 | # Virtual environments 12 | venv/ 13 | env/ 14 | .env/ 15 | .venv/ 16 | 17 | # IDE specific files 18 | .idea/ 19 | .vscode/ 20 | *.swp 21 | *.swo 22 | .DS_Store 23 | 24 | # Jupyter Notebook 25 | .ipynb_checkpoints 26 | *.ipynb_checkpoints/ 27 | 28 | # Local development settings 29 | .env 30 | .env.local 31 | 32 | # Test cache 33 | .pytest_cache/ 34 | .coverage 35 | htmlcov/ 36 | 37 | # Logs 38 | *.log 39 | logs/ 40 | 41 | # Database 42 | *.db 43 | *.sqlite3 44 | 45 | # Documentation 46 | docs/_build/ 47 | 48 | # Dependencies 49 | pip-log.txt 50 | pip-delete-this-directory.txt 51 | 52 | # add .DS_Store on any location in the project 53 | **/.DS_Store 54 | 55 | 56 | 57 | # add .venv to ignore 58 | .venv/ 59 | 60 | -------------------------------------------------------------------------------- /benchmark_stock_analysis/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Florenz23/ai-agent-videos/4d06a1d2956ea7f16b8e11074e71f5c16e91f41d/benchmark_stock_analysis/.DS_Store -------------------------------------------------------------------------------- /benchmark_stock_analysis/agent_zero/benchmkark.txt: -------------------------------------------------------------------------------- 1 | Agent Zero 2 | - This run's cost $0.03773053 --> 3,8 cents 3 | - total_tokens= 94326 4 | - lines of code beside tool: 0 5 | - lines of code for tool usage: 0 6 | - execution time: (100s + 90s + 92s) / 3 = 94 seconds average 7 | - libraries to install to make it work : cloning repo and install requirements, and docker 8 | - tricky parts / settings to make it work /deeper knowledge and research required : work_dir usage 9 | - what is nice: easy to use, debugs itself , saves you lots of time 10 | - what is not so nice: not easy to install, need dockeer, costs are difficult to track, no good documentation, not scalable, results are not very consistent 11 | - ease of use : easy 12 | - summary: interesting approach but not really an agentic framework -------------------------------------------------------------------------------- /benchmark_stock_analysis/agent_zero/concept.txt: -------------------------------------------------------------------------------- 1 | AI Agent Framework Benchmark Serie (4/5) 2 | 3 | AI Stock Analyst (agent zero) 4 | 5 | - get ticker information from yfinance api 6 | - get warren buffet principles from a file, then analyse the stock 7 | - write the results to a file -------------------------------------------------------------------------------- /benchmark_stock_analysis/agent_zero/prompt.txt: -------------------------------------------------------------------------------- 1 | description: 2 | first get the ticker_symbol from ticker_list.txt 3 | then for the {ticker_symbol} fetch the data using yfinance pip library 4 | use the following kpis 5 | Ticker Kpis: 6 | - Ticker Symbol 7 | - Company Name 8 | - Current Price 9 | - 52-Week High 10 | - 52-Week Low 11 | - Market Cap 12 | - P/E Ratio 13 | - P/B Ratio 14 | - Debt-to-Equity Ratio 15 | - Current Ratio 16 | - Dividend Yield (%) 17 | - 5-Year Revenue Growth Rate (%) 18 | - Free Cash Flow 19 | - Profit Margin 20 | - Operating Margin 21 | - Earnings Growth 22 | - Revenue Growth 23 | - Analyst Target Price 24 | - Beta 25 | then get warren buffett's investment principles by opening 26 | the file warren_buffet_investement_principles.txt 27 | then you provide a comprehensive analysis of the ticker 28 | write short and concise the pros why warren buffett would invest in 29 | this company and the cons why he wouldn't 30 | then summarize the company evaluation and provide a recommendation 31 | then you give a warren buffet buy recomendation from 0 to 10 (10 is best) 32 | finally write the result to the file stock_analysis.txt 33 | expected_output: 34 | - Pros why Warren Buffett would invest in this company 35 | - Cons why Warren Buffett wouldn't invest in this company 36 | - Company Evaluation Summary 37 | - Warren Buffet Buy Recommendation -------------------------------------------------------------------------------- /benchmark_stock_analysis/agent_zero/start_prompt.txt: -------------------------------------------------------------------------------- 1 | get your instructions from prompt.txt -------------------------------------------------------------------------------- /benchmark_stock_analysis/agent_zero/warren_buffet_investement_principles.txt: -------------------------------------------------------------------------------- 1 | Value investing: Buffett looks for undervalued companies - those trading below their intrinsic value. He aims to buy great businesses at fair prices, rather than fair businesses at great prices. 2 | Long-term perspective: He invests with a long-term outlook, often holding stocks for decades. This aligns with his belief that the stock market is unpredictable in the short term but tends to rise over the long term. 3 | Understanding the business: Buffett only invests in companies and industries he thoroughly understands. This principle helps him better assess the company's potential and risks. 4 | Competitive advantage: He looks for companies with a strong "economic moat" - a sustainable competitive advantage that protects the company from competitors. 5 | Quality management: Buffett places high importance on honest, competent management teams that act in the best interests of shareholders. 6 | Financial health: He prefers companies with strong balance sheets, consistent earnings, high return on equity, and low debt. 7 | Predictable earnings: Buffett favors businesses with steady and predictable earnings rather than those in volatile or cyclical industries. 8 | Margin of safety: He always aims to buy stocks with a significant margin of safety - the difference between the intrinsic value of a stock and its market price. 9 | Dividend policy: While not a strict requirement, Buffett often favors companies that pay dividends and have a history of increasing them. 10 | Circle of competence: He sticks to investments within his "circle of competence" - areas where he has deep knowledge and expertise. -------------------------------------------------------------------------------- /benchmark_stock_analysis/autogen/autogen_stock_analysis.py: -------------------------------------------------------------------------------- 1 | from typing import Annotated, Literal 2 | import os 3 | 4 | from autogen import ConversableAgent 5 | from autogen import register_function 6 | import pprint 7 | 8 | from dotenv import load_dotenv 9 | load_dotenv() 10 | from autogen import ConversableAgent 11 | from tools.yahoo_finance import yahoo_finance_tool 12 | import time 13 | 14 | llm_config = { 15 | "model": "gpt-4o-mini", 16 | "cache_seed": None, 17 | } 18 | 19 | start_time = time.time() 20 | 21 | 22 | def read_file(file_path: str) -> str: 23 | with open(file_path, "r") as file: 24 | return file.read() 25 | 26 | def write_file(file_path: str, content: str) -> None: 27 | with open(file_path, "w") as file: 28 | file.write(content) 29 | 30 | # Let's first define the assistant agent that suggests tool calls. 31 | assistant = ConversableAgent( 32 | name="Assistant", 33 | system_message="You are a helpful AI assistant. " 34 | "Return 'TERMINATE' when the task is done.", 35 | llm_config=llm_config, 36 | ) 37 | 38 | # The user proxy agent is used for interacting with the assistant agent 39 | # and executes tool calls. 40 | user_proxy = ConversableAgent( 41 | name="User", 42 | llm_config = False, 43 | is_termination_msg=lambda msg: msg.get("content") is not None and "TERMINATE" in msg["content"], 44 | human_input_mode="NEVER", 45 | ) 46 | 47 | # Register the calculator function to the two agents. 48 | register_function( 49 | yahoo_finance_tool, 50 | caller=assistant, # The assistant agent can suggest calls to the calculator. 51 | executor=user_proxy, # The user proxy agent can execute the calculator calls. 52 | name="yahoo_finance_tool", # By default, the function name is used as the tool name. 53 | description="Input: Ticker symbol of a stock, it will return stock data", # A description of the tool. 54 | ) 55 | 56 | # Register the read_file function to the two agents. 57 | register_function( 58 | read_file, 59 | caller=assistant, # The assistant agent can suggest calls to the read_file function. 60 | executor=user_proxy, # The user proxy agent can execute the read_file calls. 61 | name="read_file", # By default, the function name is used as the tool name. 62 | description="Read a file", # A description of the tool. 63 | ) 64 | 65 | # Register the write_file function to the two agents. 66 | register_function( 67 | write_file, 68 | caller=assistant, # The assistant agent can suggest calls to the write_file function. 69 | executor=user_proxy, # The user proxy agent can execute the write_file calls. 70 | name="write_file", # By default, the function name is used as the tool name. 71 | description="Write to a file", # A description of the tool. 72 | ) 73 | 74 | ticker_symbol = "AAPL" 75 | 76 | user_message = f""" 77 | description: 78 | first for a given ticker: {ticker_symbol} fetch the data using the yahoo_finance_tool 79 | then get warren buffett's investment principles by opening 80 | the file 81 | workflows/stock_analysis/warren_buffet_investement_principles.txt 82 | then you provide a comprehensive analysis of the ticker 83 | write short and concise the pros why warren buffett would invest in 84 | this company and the cons why he wouldn't 85 | then summarize the company evaluation and provide a recommendation 86 | then you give a warren buffet buy recomendation from 0 to 10 (10 is best) 87 | finally write the result to the file 88 | workflows/stock_analysis/stock_analysis_autogen/stock_analysis.txt 89 | expected_output: 90 | - Pros why Warren Buffett would invest in this company 91 | - Cons why Warren Buffett wouldn't invest in this company 92 | - Company Evaluation Summary 93 | - Warren Buffet Buy Recommendation 94 | """ 95 | 96 | chat_result = user_proxy.initiate_chat(assistant, message=user_message) 97 | 98 | pprint.pprint(chat_result.cost) 99 | #print needed time 100 | print("--- %s seconds ---" % (time.time() - start_time)) 101 | 102 | 103 | -------------------------------------------------------------------------------- /benchmark_stock_analysis/autogen/benchmark.txt: -------------------------------------------------------------------------------- 1 | autogen 2 | - This run's cost $0.00064075 --> 0,06 cents 3 | - total_tokens= 3089 4 | - lines of code beside tool: 107 5 | - lines of code for tool usage: 56 6 | - execution time: (9.6s + 9.2s + 8.7s) / 3 = 9.24 seconds average 7 | - libraries to install to make it work : yfinance, pyautogen==0.2.25 8 | - tricky parts / settings to make it work /deeper knowledge and research required ( none ) 9 | - what is nice: well documented with many examples and tutorials, video tutorial 10 | - what is not so nice: its from microsoft 11 | - ease of use : easy 12 | - summary: powerful but not extremely powerful, easy to use with medium programming skills -------------------------------------------------------------------------------- /benchmark_stock_analysis/autogen/concept.txt: -------------------------------------------------------------------------------- 1 | AI Agent Framework Benchmark Serie (3/5) 2 | 3 | AI Stock Analyst (autogen) 4 | 5 | - get ticker information from yfinance api 6 | - get warren buffet principles from a file, then analyse the stock 7 | - write the results to a file -------------------------------------------------------------------------------- /benchmark_stock_analysis/autogen/stock_analysis.txt: -------------------------------------------------------------------------------- 1 | ### Apple Inc. (AAPL) Stock Analysis 2 | 3 | **Pros why Warren Buffett would invest in this company:** 4 | - **Strong Brand and Competitive Advantage:** Apple has a strong economic moat due to its brand loyalty and ecosystem of products and services. 5 | - **Consistent Financial Performance:** The company has a high profit margin (26.44) and solid operating margin (29.56). It also shows steady revenue growth (4.9%). 6 | - **Strong Cash Flow:** With a free cash flow of over $86 billion, Apple has the liquidity to reinvest in the business or return capital to shareholders. 7 | - **Quality Management:** Apple exhibits competent management that focuses on innovation and long-term growth. 8 | - **Consistent Dividend Payout:** The company pays dividends, which aligns with Buffett's preference for companies that return value to shareholders. 9 | 10 | **Cons why Warren Buffett wouldn't invest in this company:** 11 | - **High P/E Ratio:** With a P/E ratio of 34.12, Apple might be considered overvalued compared to its earnings potential. 12 | - **High Debt Levels:** The debt-to-equity ratio of 151.86 raises concerns about the company's leverage and financial risk. 13 | - **Market Saturation Risks:** As Apple’s core markets mature, growth may slow, which could impact earnings potential. 14 | 15 | **Company Evaluation Summary:** 16 | Apple Inc. continues to demonstrate strong financial performance with consistent growth and a robust brand presence. However, its high valuation metrics and increasing debt levels may warrant caution for value investors. Apple's ability to innovate and maintain its competitive edge will be crucial in the coming years. 17 | 18 | **Warren Buffet Buy Recommendation: 7/10** 19 | Overall, while Apple Inc. presents a compelling investment opportunity with strong fundamentals, its valuation and potential market risks should be considered before making an investment. 20 | -------------------------------------------------------------------------------- /benchmark_stock_analysis/autogen/tools/__pycache__/yahoo_finance.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Florenz23/ai-agent-videos/4d06a1d2956ea7f16b8e11074e71f5c16e91f41d/benchmark_stock_analysis/autogen/tools/__pycache__/yahoo_finance.cpython-312.pyc -------------------------------------------------------------------------------- /benchmark_stock_analysis/autogen/tools/yahoo_finance.py: -------------------------------------------------------------------------------- 1 | import yfinance as yf 2 | 3 | def yahoo_finance_tool(ticker_sombol: str) -> dict: 4 | """ 5 | Input: Ticker symbol of a stock, it will return stock data 6 | """ 7 | # Fetch the stock data 8 | stock = yf.Ticker(ticker_sombol) 9 | 10 | # Get the info dictionary 11 | info = stock.info 12 | 13 | # Get historical data 14 | history = stock.history(period="5y") 15 | 16 | # Calculate 52-Week High/Low 17 | week_52_high = history['High'].tail(252).max() 18 | week_52_low = history['Low'].tail(252).min() 19 | 20 | # Calculate 5-year revenue growth rate 21 | financials = stock.financials 22 | if not financials.empty and 'Total Revenue' in financials.index: 23 | revenue_5y = financials.loc['Total Revenue'].iloc[:5] 24 | revenue_growth = (revenue_5y.iloc[0] / revenue_5y.iloc[-1]) ** (1/5) - 1 25 | else: 26 | revenue_growth = 'N/A' 27 | 28 | # Prepare the analysis results 29 | analysis = { 30 | 'Ticker Symbol': ticker_sombol, 31 | 'Company Name': info.get('longName', 'N/A'), 32 | 'Current Price': info.get('currentPrice', 'N/A'), 33 | '52-Week High': round(week_52_high, 2), 34 | '52-Week Low': round(week_52_low, 2), 35 | 'Market Cap': info.get('marketCap', 'N/A'), 36 | 'P/E Ratio': info.get('trailingPE', 'N/A'), 37 | 'P/B Ratio': info.get('priceToBook', 'N/A'), 38 | 'Debt-to-Equity Ratio': info.get('debtToEquity', 'N/A'), 39 | 'Current Ratio': info.get('currentRatio', 'N/A'), 40 | 'Dividend Yield (%)': info.get('dividendYield', 'N/A'), 41 | '5-Year Revenue Growth Rate (%)': revenue_growth if isinstance(revenue_growth, float) else 'N/A', 42 | 'Free Cash Flow': info.get('freeCashflow', 'N/A'), 43 | 'Profit Margin': info.get('profitMargins', 'N/A'), 44 | 'Operating Margin': info.get('operatingMargins', 'N/A'), 45 | 'Earnings Growth': info.get('earningsGrowth', 'N/A'), 46 | 'Revenue Growth': info.get('revenueGrowth', 'N/A'), 47 | 'Analyst Target Price': info.get('targetMedianPrice', 'N/A'), 48 | 'Beta': info.get('beta', 'N/A') 49 | } 50 | 51 | # Convert percentage values 52 | for key in ['Dividend Yield (%)', '5-Year Revenue Growth Rate (%)', 'Profit Margin', 'Operating Margin', 'Earnings Growth', 'Revenue Growth']: 53 | if analysis[key] != 'N/A': 54 | analysis[key] = round(analysis[key] * 100, 2) 55 | 56 | return analysis 57 | 58 | -------------------------------------------------------------------------------- /benchmark_stock_analysis/autogen/warren_buffet_investement_principles.txt: -------------------------------------------------------------------------------- 1 | Value investing: Buffett looks for undervalued companies - those trading below their intrinsic value. He aims to buy great businesses at fair prices, rather than fair businesses at great prices. 2 | Long-term perspective: He invests with a long-term outlook, often holding stocks for decades. This aligns with his belief that the stock market is unpredictable in the short term but tends to rise over the long term. 3 | Understanding the business: Buffett only invests in companies and industries he thoroughly understands. This principle helps him better assess the company's potential and risks. 4 | Competitive advantage: He looks for companies with a strong "economic moat" - a sustainable competitive advantage that protects the company from competitors. 5 | Quality management: Buffett places high importance on honest, competent management teams that act in the best interests of shareholders. 6 | Financial health: He prefers companies with strong balance sheets, consistent earnings, high return on equity, and low debt. 7 | Predictable earnings: Buffett favors businesses with steady and predictable earnings rather than those in volatile or cyclical industries. 8 | Margin of safety: He always aims to buy stocks with a significant margin of safety - the difference between the intrinsic value of a stock and its market price. 9 | Dividend policy: While not a strict requirement, Buffett often favors companies that pay dividends and have a history of increasing them. 10 | Circle of competence: He sticks to investments within his "circle of competence" - areas where he has deep knowledge and expertise. -------------------------------------------------------------------------------- /benchmark_stock_analysis/crewai/benchmark.txt: -------------------------------------------------------------------------------- 1 | crewai 2 | - This run's cost $0.000684 3 | - total_tokens=5829 prompt_tokens=4561 completion_tokens=1268 successful_requests=5 4 | - lines of code beside tool: 124 5 | - lines of code for tool usage: 86 6 | - “tricky” settings to make it work /deeper knowledge and research required ( output_file, delegation_false, using mini, custom tool usage a little tricky, docs not that clear ) 7 | - libraries to install to make it work : yfinance, crewai, crewai[tools], langchain-openai 8 | - execution time: 20, 26, 25 —> 23,5 seconds 9 | - ease of use : medium -------------------------------------------------------------------------------- /benchmark_stock_analysis/crewai/get_stock_news.py: -------------------------------------------------------------------------------- 1 | # stock_news.py 2 | 3 | import yfinance as yf 4 | from datetime import datetime 5 | 6 | def get_company_news(ticker, num_articles=8): 7 | stock = yf.Ticker(ticker) 8 | all_news = stock.news 9 | 10 | # Get the latest news articles 11 | latest_news = [] 12 | for article in all_news[:num_articles]: 13 | latest_news.append({ 14 | 'Title': article['title'], 15 | 'Publisher': article['publisher'], 16 | 'Link': article['link'], 17 | 'Date': datetime.fromtimestamp(article['providerPublishTime']).strftime('%Y-%m-%d %H:%M:%S') 18 | }) 19 | 20 | return latest_news 21 | 22 | if __name__ == "__main__": 23 | # Example usage 24 | nvidia_news = get_company_news('NVDA') 25 | for i, article in enumerate(nvidia_news, 1): 26 | print(f"\n{i}. {article['Title']}") 27 | print(f" Publisher: {article['Publisher']}") 28 | print(f" Date: {article['Date']}") 29 | print(f" Link: {article['Link']}") -------------------------------------------------------------------------------- /benchmark_stock_analysis/crewai/main.py: -------------------------------------------------------------------------------- 1 | from crewai import Agent, Task, Crew, Process 2 | 3 | from tools.YFinanceStockAnalysisTool import YFinanceStockAnalysisTool 4 | from langchain_openai import ChatOpenAI 5 | from crewai_tools import FileReadTool 6 | import os 7 | import time 8 | 9 | from dotenv import load_dotenv 10 | load_dotenv() 11 | 12 | start_time = time.time() 13 | 14 | yfinance_stock_data_tool = YFinanceStockAnalysisTool() 15 | file_read_tool = FileReadTool(file_path='workflows/stock_analysis/warren_buffet_investement_principles.txt') 16 | 17 | # os.environ['OPENAI_MODEL_NAME']='gpt-4o-mini' # Adjust based on available model 18 | 19 | import agentops 20 | 21 | agentops.init(default_tags=["stock_research"]) 22 | 23 | AGENT_MOODEL = ChatOpenAI( 24 | model = "gpt-4o-mini" 25 | ) 26 | 27 | # Agent definitions 28 | stock_research_manager = Agent( 29 | role='Stock Research Manager', 30 | verbose=True, 31 | goal='Gather relevant stock news and data', 32 | backstory=""" 33 | You are a methodical manager supervising stock research. 34 | You prevent process loops and maintain high-quality output. 35 | """, 36 | tools=[], 37 | memory=True, 38 | llm=AGENT_MOODEL 39 | ) 40 | 41 | senior_stock_analyst = Agent( 42 | role='Senior Stock Analyst', 43 | goal='Analyze the provided stock data and news to give investment advice', 44 | backstory=""" 45 | You are an AI-powered senior analyst applying Warren Buffett's 46 | investment principles. You are very strict with your recommendations 47 | and only recommend the best stocks. 48 | """, 49 | tools=[], 50 | memory=True, 51 | llm=AGENT_MOODEL, 52 | verbose=True, 53 | allow_delegation=False 54 | ) 55 | 56 | # Task definitions 57 | get_stock_analysis_for_ticker = Task( 58 | description=""" 59 | for a given ticker: {ticker} fetch the data from yfinance and return data to 60 | the next agent 61 | """, 62 | expected_output=""" 63 | Ticker Kpis: 64 | - Ticker Symbol 65 | - Company Name 66 | - Current Price 67 | - 52-Week High 68 | - 52-Week Low 69 | - Market Cap 70 | - P/E Ratio 71 | - P/B Ratio 72 | - Debt-to-Equity Ratio 73 | - Current Ratio 74 | - Dividend Yield (%) 75 | - 5-Year Revenue Growth Rate (%) 76 | - Free Cash Flow 77 | - Profit Margin 78 | - Operating Margin 79 | - Earnings Growth 80 | - Revenue Growth 81 | - Analyst Target Price 82 | - Beta 83 | """, 84 | tools=[yfinance_stock_data_tool], 85 | agent=stock_research_manager 86 | ) 87 | 88 | analyse_ticker = Task( 89 | description=""" 90 | first you get warren buffett's investment principles by using the 91 | file read tool 92 | then you provide a comprehensive analysis of the ticker 93 | write short and concise the pros why warren buffett would invest in 94 | this company and the cons why he wouldn't 95 | then summarize the company evaluation and provide a recommendation 96 | then you give a warren buffet buy recomendation from 0 to 10 (10 is best) 97 | """, 98 | expected_output=""" 99 | - Pros why Warren Buffett would invest in this company 100 | - Cons why Warren Buffett wouldn't invest in this company 101 | - Company Evaluation Summary 102 | - Warren Buffet Buy Recommendation 103 | """, 104 | tools=[file_read_tool], 105 | agent=senior_stock_analyst, 106 | output_file='workflows/stock_analysis/stock_analysis.txt' 107 | ) 108 | 109 | 110 | # Crew definition 111 | stock_analysis_crew = Crew( 112 | agents=[stock_research_manager, senior_stock_analyst], 113 | tasks=[get_stock_analysis_for_ticker, analyse_ticker], 114 | process=Process.sequential 115 | ) 116 | 117 | # ticker of coca cola: KO 118 | inputs = { 119 | "ticker": "NVDA" 120 | } 121 | 122 | # Kickoff the process 123 | result = stock_analysis_crew.kickoff(inputs=inputs) 124 | print("Crew usage", stock_analysis_crew.usage_metrics) 125 | print(result) 126 | 127 | agentops.end_session('Success') 128 | print("Time taken: ", time.time() - start_time) 129 | -------------------------------------------------------------------------------- /benchmark_stock_analysis/crewai/stock_analysis.txt: -------------------------------------------------------------------------------- 1 | **Pros why Warren Buffett would invest in NVIDIA Corporation (NVDA):** 2 | 1. **Strong Competitive Advantage:** NVIDIA has a significant economic moat due to its leadership in the GPU market, especially in gaming and data centers, which are essential for AI and machine learning applications. 3 | 2. **High Profit Margins:** With a profit margin of 53.4% and an operating margin of 64.93%, NVIDIA demonstrates exceptional profitability that aligns with Buffett's preference for financially healthy companies. 4 | 3. **Robust Revenue and Earnings Growth:** NVIDIA's revenue growth of 262.1% and earnings growth of 650.0% indicate a rapidly expanding business, fitting Buffett's criteria for investing in companies with predictable and strong growth. 5 | 4. **Solid Financial Health:** The current ratio of 3.529 indicates strong liquidity, and the free cash flow of approximately $29 billion suggests that the company is generating significant cash to reinvest in growth or return to shareholders. 6 | 5. **Quality Management:** NVIDIA has a reputation for innovative management, particularly under CEO Jensen Huang, which aligns with Buffett’s focus on investing in companies led by competent management teams. 7 | 8 | **Cons why Warren Buffett wouldn't invest in NVIDIA Corporation (NVDA):** 9 | 1. **High Valuation Ratios:** The P/E ratio of 74.4152 and P/B ratio of 63.688686 suggest that NVIDIA may be overvalued compared to its earnings and book value, which could deter Buffett's value-oriented approach. 10 | 2. **High Debt-to-Equity Ratio:** With a debt-to-equity ratio of 22.866, NVIDIA's financial structure is heavily reliant on debt, which may pose risks, especially in a rising interest rate environment. 11 | 3. **Volatility:** The beta of 1.68 indicates that NVIDIA’s stock price is more volatile than the market, which is contrary to Buffett's preference for stable and predictable investments. 12 | 4. **Limited Dividend Yield:** A dividend yield of only 0.03% may not align with Buffett's inclination toward companies that provide regular income through dividends. 13 | 14 | **Company Evaluation Summary:** 15 | NVIDIA Corporation is a leading technology company with strong fundamentals, impressive growth metrics, and a solid competitive position in the GPU market. However, its high valuation and volatility raise concerns regarding its suitability as a long-term investment aligned with Buffett's principles. The company's focus on innovation and strong management could counterbalance these concerns, but the reliance on debt and market fluctuations cannot be overlooked. 16 | 17 | **Warren Buffett Buy Recommendation:** 18 | Considering the pros and cons, I would rate NVIDIA Corporation a **7 out of 10** for a potential buy. While it possesses strong growth and competitive advantages, its high valuation and financial risks are significant factors to consider. -------------------------------------------------------------------------------- /benchmark_stock_analysis/crewai/stock_summary.txt: -------------------------------------------------------------------------------- 1 | **Detailed Analysis of Apple Inc. (AAPL)** 2 | 3 | **Current Stock Information:** 4 | - **Current Price:** $225.89 5 | - **52-Week High:** $236.96 6 | - **52-Week Low:** $163.67 7 | - **P/E Ratio:** 34.38 8 | - **P/B Ratio:** 51.55 9 | - **Debt-to-Equity Ratio:** 151.86 10 | - **Dividend Yield:** 0.44% 11 | - **5-Year Average Return on Equity:** 160.58% 12 | 13 | **Pros and Cons Summary:** 14 | 15 | **Pros:** 16 | 1. **Strong Brand Loyalty and Market Position:** Apple is one of the most recognized brands globally, with a loyal customer base that consistently drives sales across its product lines. 17 | 2. **Innovation in Technology:** Recent advancements in AI technology show Apple's commitment to staying at the forefront of technological development, which could enhance user experience and drive sales. 18 | 3. **Diversified Revenue Streams:** Apple's ecosystem includes hardware, software, and services (like Apple Music and the App Store), providing resilience against market fluctuations. 19 | 4. **High Return on Equity:** With a 5-year average ROE of 160.58%, Apple demonstrates effective management and profitability relative to shareholder equity. 20 | 5. **Speculative Growth with iPhone 16:** Anticipation around the upcoming iPhone 16 could lead to increased sales and investor interest, potentially driving the stock price higher. 21 | 22 | **Cons:** 23 | 1. **High Valuation Ratios:** With a P/E ratio of 34.38 and a P/B ratio of 51.55, Apple’s stock may be considered overvalued compared to historical averages or industry peers, posing a risk for investors. 24 | 2. **High Debt-to-Equity Ratio:** A debt-to-equity ratio of 151.86 indicates that Apple relies heavily on debt financing, which could introduce financial risk, especially in a rising interest rate environment. 25 | 3. **Market Saturation:** The smartphone market is increasingly saturated, which could limit future growth in iPhone sales, a significant revenue driver for the company. 26 | 4. **Dependence on Product Releases:** Revenue and stock performance can be significantly impacted by new product launches. Any delays or underwhelming products could negatively affect investor sentiment. 27 | 5. **Dividend Yield Limitation:** The current dividend yield of 0.44% is relatively low, which may be unattractive for income-focused investors. 28 | 29 | **Company Evaluation:** 30 | 31 | Apple Inc. continues to demonstrate robust financial health and operational efficiency, evidenced by its strong ROE and diverse product offerings. The company has consistently outperformed many competitors and maintains a significant market share in the technology sector. However, its high valuation ratios and reliance on debt raise concerns about long-term sustainability and risk exposure. 32 | 33 | Recent advancements in AI technology could provide new growth avenues, while speculation about the iPhone 16 may boost short-term investor sentiment. Nonetheless, it's crucial to monitor market saturation levels and competitive pressures, as well as to assess how effectively Apple can innovate and maintain its leadership position. 34 | 35 | **Investment Recommendation:** 36 | 37 | Considering the analysis, Apple Inc. (AAPL) is a solid investment for those willing to accept moderate risk for potential growth. While the stock is currently trading at a high valuation, the company's historical performance, strong brand loyalty, and diversification into AI and services present a compelling case for long-term investment. However, potential investors should remain cautious of the high debt levels and monitor upcoming product launches closely. 38 | 39 | **Recommendation:** 40 | - **Long-Term Hold:** For existing investors, holding onto AAPL shares is advisable due to its strong fundamentals and growth potential. 41 | - **Cautious Buy:** For new investors, consider entering at a lower price point or waiting for market corrections to capitalize on potential future gains, particularly in light of upcoming product releases like the iPhone 16. 42 | 43 | In conclusion, while there are risks involved, Apple's strong market position, innovation capabilities, and diversified revenue streams provide a favorable outlook for long-term growth, making it a worthwhile consideration for investors. -------------------------------------------------------------------------------- /benchmark_stock_analysis/crewai/tools/YFinanceNewsTool.py: -------------------------------------------------------------------------------- 1 | from crewai_tools import BaseTool 2 | from pydantic import BaseModel, Field 3 | import yfinance as yf 4 | from datetime import datetime 5 | from typing import Type 6 | 7 | # Define the input schema using Pydantic 8 | class YFinanceNewsToolInput(BaseModel): 9 | """Input schema for YFinanceNewsTool.""" 10 | ticker: str = Field(..., description="Stock ticker symbol (e.g., 'AAPL' for Apple Inc.)") 11 | num_articles: int = Field(8, description="Number of latest news articles to retrieve") 12 | 13 | # Define the tool class 14 | class YFinanceNewsTool(BaseTool): 15 | name: str = "YFinance News Tool" 16 | description: str = "Fetches the latest news articles for a given stock ticker using yfinance." 17 | args_schema: Type[BaseModel] = YFinanceNewsToolInput 18 | 19 | def _run(self, ticker: str, num_articles: int = 8) -> str: 20 | """ 21 | Fetches the latest news articles for a given stock ticker using yfinance. 22 | 23 | :param ticker: Stock ticker symbol (e.g., 'AAPL' for Apple Inc.) 24 | :param num_articles: Number of latest news articles to retrieve (default: 8) 25 | :return: A string containing the titles, publishers, dates, and links of the latest news articles. 26 | """ 27 | stock = yf.Ticker(ticker) 28 | all_news = stock.news 29 | 30 | # Get the latest news articles 31 | latest_news = [] 32 | for article in all_news[:num_articles]: 33 | latest_news.append({ 34 | 'Title': article['title'], 35 | 'Publisher': article['publisher'], 36 | 'Link': article['link'], 37 | 'Date': datetime.fromtimestamp(article['providerPublishTime']).strftime('%Y-%m-%d %H:%M:%S') 38 | }) 39 | 40 | # Formatting the news articles for output 41 | output = [] 42 | for i, article in enumerate(latest_news, 1): 43 | output.append(f"{i}. {article['Title']}\n Publisher: {article['Publisher']}\n Date: {article['Date']}\n Link: {article['Link']}") 44 | 45 | return "\n\n".join(output) 46 | 47 | async def _arun(self, ticker: str, num_articles: int = 8) -> str: 48 | """Asynchronous version of the _run method.""" 49 | return self._run(ticker, num_articles) 50 | 51 | # Example usage within CrewAI 52 | if __name__ == "__main__": 53 | tool_instance = YFinanceNewsTool() 54 | nvidia_news = tool_instance.run(ticker='NVDA') 55 | print(nvidia_news) 56 | -------------------------------------------------------------------------------- /benchmark_stock_analysis/crewai/tools/YFinanceStockAnalysisTool.py: -------------------------------------------------------------------------------- 1 | from crewai_tools import BaseTool 2 | from pydantic import BaseModel, Field 3 | import yfinance as yf 4 | from typing import Type 5 | 6 | # Define the input schema using Pydantic 7 | class YFinanceStockAnalysisToolInput(BaseModel): 8 | """Input schema for YFinanceStockAnalysisTool.""" 9 | ticker: str = Field(..., description="Stock ticker symbol (e.g., 'AAPL' for Apple Inc.)") 10 | 11 | # Define the tool class 12 | class YFinanceStockAnalysisTool(BaseTool): 13 | name: str = "YFinance Stock Analysis Tool" 14 | description: str = "Fetches and analyzes stock data for a given ticker using yfinance, including Buffett-style analysis." 15 | args_schema: Type[BaseModel] = YFinanceStockAnalysisToolInput 16 | 17 | def _run(self, ticker: str) -> str: 18 | """ 19 | Fetches and analyzes stock data for a given ticker using yfinance, including Buffett-style analysis. 20 | :param ticker: Stock ticker symbol (e.g., 'AAPL' for Apple Inc.) 21 | :return: A string containing the stock's financial KPIs and Buffett-style analysis. 22 | """ 23 | # Fetch the stock data 24 | stock = yf.Ticker(ticker) 25 | 26 | # Get the info dictionary 27 | info = stock.info 28 | 29 | # Get historical data 30 | history = stock.history(period="5y") 31 | 32 | # Calculate 52-Week High/Low 33 | week_52_high = history['High'].tail(252).max() 34 | week_52_low = history['Low'].tail(252).min() 35 | 36 | # Calculate 5-year revenue growth rate 37 | financials = stock.financials 38 | if not financials.empty and 'Total Revenue' in financials.index: 39 | revenue_5y = financials.loc['Total Revenue'].iloc[:5] 40 | revenue_growth = (revenue_5y.iloc[0] / revenue_5y.iloc[-1]) ** (1/5) - 1 if len(revenue_5y) >= 5 else None 41 | else: 42 | revenue_growth = None 43 | 44 | # Prepare the analysis results 45 | analysis = { 46 | 'Ticker Symbol': ticker, 47 | 'Company Name': info.get('longName', 'N/A'), 48 | 'Current Price': info.get('currentPrice', 'N/A'), 49 | '52-Week High': round(week_52_high, 2), 50 | '52-Week Low': round(week_52_low, 2), 51 | 'Market Cap': info.get('marketCap', 'N/A'), 52 | 'P/E Ratio': info.get('trailingPE', 'N/A'), 53 | 'P/B Ratio': info.get('priceToBook', 'N/A'), 54 | 'Debt-to-Equity Ratio': info.get('debtToEquity', 'N/A'), 55 | 'Current Ratio': info.get('currentRatio', 'N/A'), 56 | 'Dividend Yield (%)': info.get('dividendYield', 'N/A'), 57 | '5-Year Revenue Growth Rate (%)': revenue_growth, 58 | 'Free Cash Flow': info.get('freeCashflow', 'N/A'), 59 | 'Profit Margin': info.get('profitMargins', 'N/A'), 60 | 'Operating Margin': info.get('operatingMargins', 'N/A'), 61 | 'Earnings Growth': info.get('earningsGrowth', 'N/A'), 62 | 'Revenue Growth': info.get('revenueGrowth', 'N/A'), 63 | 'Analyst Target Price': info.get('targetMedianPrice', 'N/A'), 64 | 'Beta': info.get('beta', 'N/A'), 65 | '5-Year Average Return on Equity (%)': info.get('returnOnEquity', 'N/A') 66 | } 67 | 68 | # Convert percentage values 69 | for key in ['Dividend Yield (%)', '5-Year Revenue Growth Rate (%)', 'Profit Margin', 'Operating Margin', 'Earnings Growth', 'Revenue Growth', '5-Year Average Return on Equity (%)']: 70 | if analysis[key] not in ['N/A', None]: 71 | analysis[key] = round(analysis[key] * 100, 2) 72 | 73 | # Format the analysis results for output 74 | output = "\n".join([f"{key}: {value}" for key, value in analysis.items()]) 75 | 76 | return output 77 | 78 | async def _arun(self, ticker: str) -> str: 79 | """Asynchronous version of the _run method.""" 80 | return self._run(ticker) 81 | 82 | # Example usage within CrewAI 83 | if __name__ == "__main__": 84 | tool_instance = YFinanceStockAnalysisTool() 85 | nvidia_analysis = tool_instance.run(ticker='NVDA') 86 | print(nvidia_analysis) -------------------------------------------------------------------------------- /benchmark_stock_analysis/crewai/tools/__pycache__/YFinanceNewsTool.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Florenz23/ai-agent-videos/4d06a1d2956ea7f16b8e11074e71f5c16e91f41d/benchmark_stock_analysis/crewai/tools/__pycache__/YFinanceNewsTool.cpython-312.pyc -------------------------------------------------------------------------------- /benchmark_stock_analysis/crewai/tools/__pycache__/YFinanceStockAnalysisTool.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Florenz23/ai-agent-videos/4d06a1d2956ea7f16b8e11074e71f5c16e91f41d/benchmark_stock_analysis/crewai/tools/__pycache__/YFinanceStockAnalysisTool.cpython-312.pyc -------------------------------------------------------------------------------- /benchmark_stock_analysis/crewai/warren_buffet_investement_principles.txt: -------------------------------------------------------------------------------- 1 | Value investing: Buffett looks for undervalued companies - those trading below their intrinsic value. He aims to buy great businesses at fair prices, rather than fair businesses at great prices. 2 | Long-term perspective: He invests with a long-term outlook, often holding stocks for decades. This aligns with his belief that the stock market is unpredictable in the short term but tends to rise over the long term. 3 | Understanding the business: Buffett only invests in companies and industries he thoroughly understands. This principle helps him better assess the company's potential and risks. 4 | Competitive advantage: He looks for companies with a strong "economic moat" - a sustainable competitive advantage that protects the company from competitors. 5 | Quality management: Buffett places high importance on honest, competent management teams that act in the best interests of shareholders. 6 | Financial health: He prefers companies with strong balance sheets, consistent earnings, high return on equity, and low debt. 7 | Predictable earnings: Buffett favors businesses with steady and predictable earnings rather than those in volatile or cyclical industries. 8 | Margin of safety: He always aims to buy stocks with a significant margin of safety - the difference between the intrinsic value of a stock and its market price. 9 | Dividend policy: While not a strict requirement, Buffett often favors companies that pay dividends and have a history of increasing them. 10 | Circle of competence: He sticks to investments within his "circle of competence" - areas where he has deep knowledge and expertise. -------------------------------------------------------------------------------- /benchmark_stock_analysis/langraph/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Florenz23/ai-agent-videos/4d06a1d2956ea7f16b8e11074e71f5c16e91f41d/benchmark_stock_analysis/langraph/.DS_Store -------------------------------------------------------------------------------- /benchmark_stock_analysis/langraph/benchmark.txt: -------------------------------------------------------------------------------- 1 | langraph 2 | - This run's cost $0.00041935 3 | - total_tokens=1,128.67 4 | - lines of code beside tool: 81 5 | - lines of code for tool usage: 60 6 | - execution time: (10.15s + 13.88s + 22.26s) / 3 = 15.43s average 7 | - libraries to install to make it work : yfinance, langgraph, langchain-openai 8 | - tricky parts / settings to make it work /deeper knowledge and research required ( trying out and testing many tutorials and examples, adjust tutoral to needs, multi agent systems not self explaining ) 9 | - what is nice: well documented with many examples and tutorials 10 | - what is not so nice: many tutorials dont work, maybe outdated 11 | - ease of use : hard 12 | - summary: langgraph is a very powerful tool, good programming skills required -------------------------------------------------------------------------------- /benchmark_stock_analysis/langraph/concept.txt: -------------------------------------------------------------------------------- 1 | AI Agent Framework Benchmark Serie (2/5) 2 | 3 | AI Stock Analyst (langgraph) 4 | 5 | - get ticker information from yfinance api 6 | - get warren buffet principles from a file, then analyse the stock 7 | - write the results to a file -------------------------------------------------------------------------------- /benchmark_stock_analysis/langraph/graph_concept.txt: -------------------------------------------------------------------------------- 1 | 2 | I want to do the following: 3 | 1. user enters a ticker symbol 4 | 2. get ticker information from yahoo finance 5 | 3. get warren buffet investement principles from a file 6 | 4. create a stock investement analyse based on the investement principles and stock data 7 | 5. save the output data in a file -------------------------------------------------------------------------------- /benchmark_stock_analysis/langraph/stock_analysis.py: -------------------------------------------------------------------------------- 1 | import os 2 | from langchain import hub 3 | from langchain.agents import AgentExecutor, create_tool_calling_agent 4 | from langchain_openai import ChatOpenAI 5 | from dotenv import load_dotenv 6 | from langchain_community.agent_toolkits import FileManagementToolkit 7 | 8 | from tools.yahoo_finance import yahoo_finance_tool 9 | 10 | import os 11 | 12 | 13 | os.environ["LANGCHAIN_TRACING_V2"] = "true" 14 | os.environ["LANGCHAIN_PROJECT"] = "stock_analysis" 15 | 16 | load_dotenv() 17 | 18 | file_management_fools = FileManagementToolkit( 19 | root_dir=str("workflows/stock_analysis/stock_analysis_langgraph"), 20 | selected_tools=["read_file", "write_file", "list_directory"], 21 | ).get_tools() 22 | read_tool, write_tool, list_tool = file_management_fools 23 | 24 | # Define tools 25 | 26 | 27 | # Set up the agent 28 | def setup_agent(): 29 | # Set up tools 30 | tools = [read_tool, write_tool, list_tool, yahoo_finance_tool] 31 | 32 | # Get the prompt 33 | prompt = hub.pull("hwchase17/openai-tools-agent") 34 | 35 | # Set up the language model 36 | llm = ChatOpenAI(model="gpt-4o-mini") 37 | 38 | # Create the agent 39 | agent = create_tool_calling_agent(llm, tools, prompt) 40 | 41 | # Create the agent executor 42 | return AgentExecutor(agent=agent, tools=tools, verbose=True) 43 | 44 | def main(): 45 | # Ensure OpenAI API key is set 46 | #ticker nvida: NVDA 47 | ticker_symbol = "AAPL" 48 | 49 | if "OPENAI_API_KEY" not in os.environ: 50 | os.environ["OPENAI_API_KEY"] = input("Please enter your OpenAI API key: ") 51 | 52 | # Set up the agent executor 53 | agent_executor = setup_agent() 54 | 55 | prompt = f""" 56 | description: 57 | first for a given ticker: {ticker_symbol} fetch the data using the yahoo_finance_tool 58 | then get warren buffett's investment principles by opening 59 | the file warren_buffet_investement_principles.txt 60 | then you provide a comprehensive analysis of the ticker 61 | write short and concise the pros why warren buffett would invest in 62 | this company and the cons why he wouldn't 63 | then summarize the company evaluation and provide a recommendation 64 | then you give a warren buffet buy recomendation from 0 to 10 (10 is best) 65 | finally write the result to the file stock_analysis.txt 66 | expected_output: 67 | - Pros why Warren Buffett would invest in this company 68 | - Cons why Warren Buffett wouldn't invest in this company 69 | - Company Evaluation Summary 70 | - Warren Buffet Buy Recommendation 71 | """ 72 | 73 | # Example invocation 74 | result = agent_executor.invoke({ 75 | "input": prompt 76 | }) 77 | 78 | print("Result:", result) 79 | 80 | if __name__ == "__main__": 81 | main() -------------------------------------------------------------------------------- /benchmark_stock_analysis/langraph/stock_analysis.txt: -------------------------------------------------------------------------------- 1 | ### Stock Analysis for Apple Inc. (AAPL) 2 | 3 | #### Pros why Warren Buffett would invest in this company: 4 | 1. **Strong Market Position**: Apple has a strong brand and a loyal customer base, giving it a significant competitive advantage. 5 | 2. **Consistent Earnings**: Apple has a history of stable revenue and profit growth, with a profit margin of 26.44% and an operating margin of 29.56%. 6 | 3. **Financial Health**: Despite a high Debt-to-Equity ratio, Apple maintains strong free cash flow, indicating financial robustness. 7 | 4. **Innovative Products**: Apple’s commitment to innovation ensures its products remain in demand, supporting long-term growth. 8 | 5. **Dividend Payments**: Apple pays dividends and has a history of increasing them, which aligns with Buffett’s preference for dividend-paying stocks. 9 | 10 | #### Cons why Warren Buffett wouldn't invest in this company: 11 | 1. **High Valuation**: With a P/E ratio of 34.46 and a P/B ratio of 51.67, Apple appears overvalued, which might not align with Buffett's principle of buying undervalued stocks. 12 | 2. **Debt Levels**: The high Debt-to-Equity ratio could be a concern, as it indicates significant leverage, which can be risky in economic downturns. 13 | 3. **Market Saturation**: The smartphone market is highly saturated, potentially limiting future growth opportunities. 14 | 15 | #### Company Evaluation Summary: 16 | Apple Inc. is a strong player in the technology sector, boasting a solid brand, innovative products, and consistent financial performance. However, its high valuation metrics and considerable debt raise concerns for value-focused investors like Warren Buffett. While it has many characteristics that Buffett admires, the current market price may not reflect a margin of safety. 17 | 18 | #### Warren Buffet Buy Recommendation: 6/10 19 | 20 | Overall, while Apple has strong fundamentals and aligns with several of Buffett’s investment principles, its high valuation and debt levels may deter a purchase at this time. A potential investor should consider waiting for a more favorable entry point. -------------------------------------------------------------------------------- /benchmark_stock_analysis/langraph/tools/__pycache__/yahoo_finance.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Florenz23/ai-agent-videos/4d06a1d2956ea7f16b8e11074e71f5c16e91f41d/benchmark_stock_analysis/langraph/tools/__pycache__/yahoo_finance.cpython-312.pyc -------------------------------------------------------------------------------- /benchmark_stock_analysis/langraph/tools/yahoo_finance.py: -------------------------------------------------------------------------------- 1 | from langchain_core.tools import tool 2 | 3 | import yfinance as yf 4 | 5 | @tool 6 | def yahoo_finance_tool(ticker_sombol: str) -> dict: 7 | """ 8 | Input: Ticker symbol of a stock, it will return stock data 9 | """ 10 | # Fetch the stock data 11 | stock = yf.Ticker(ticker_sombol) 12 | 13 | # Get the info dictionary 14 | info = stock.info 15 | 16 | # Get historical data 17 | history = stock.history(period="5y") 18 | 19 | # Calculate 52-Week High/Low 20 | week_52_high = history['High'].tail(252).max() 21 | week_52_low = history['Low'].tail(252).min() 22 | 23 | # Calculate 5-year revenue growth rate 24 | financials = stock.financials 25 | if not financials.empty and 'Total Revenue' in financials.index: 26 | revenue_5y = financials.loc['Total Revenue'].iloc[:5] 27 | revenue_growth = (revenue_5y.iloc[0] / revenue_5y.iloc[-1]) ** (1/5) - 1 28 | else: 29 | revenue_growth = 'N/A' 30 | 31 | # Prepare the analysis results 32 | analysis = { 33 | 'Ticker Symbol': ticker_sombol, 34 | 'Company Name': info.get('longName', 'N/A'), 35 | 'Current Price': info.get('currentPrice', 'N/A'), 36 | '52-Week High': round(week_52_high, 2), 37 | '52-Week Low': round(week_52_low, 2), 38 | 'Market Cap': info.get('marketCap', 'N/A'), 39 | 'P/E Ratio': info.get('trailingPE', 'N/A'), 40 | 'P/B Ratio': info.get('priceToBook', 'N/A'), 41 | 'Debt-to-Equity Ratio': info.get('debtToEquity', 'N/A'), 42 | 'Current Ratio': info.get('currentRatio', 'N/A'), 43 | 'Dividend Yield (%)': info.get('dividendYield', 'N/A'), 44 | '5-Year Revenue Growth Rate (%)': revenue_growth if isinstance(revenue_growth, float) else 'N/A', 45 | 'Free Cash Flow': info.get('freeCashflow', 'N/A'), 46 | 'Profit Margin': info.get('profitMargins', 'N/A'), 47 | 'Operating Margin': info.get('operatingMargins', 'N/A'), 48 | 'Earnings Growth': info.get('earningsGrowth', 'N/A'), 49 | 'Revenue Growth': info.get('revenueGrowth', 'N/A'), 50 | 'Analyst Target Price': info.get('targetMedianPrice', 'N/A'), 51 | 'Beta': info.get('beta', 'N/A') 52 | } 53 | 54 | # Convert percentage values 55 | for key in ['Dividend Yield (%)', '5-Year Revenue Growth Rate (%)', 'Profit Margin', 'Operating Margin', 'Earnings Growth', 'Revenue Growth']: 56 | if analysis[key] != 'N/A': 57 | analysis[key] = round(analysis[key] * 100, 2) 58 | 59 | return analysis 60 | 61 | -------------------------------------------------------------------------------- /benchmark_stock_analysis/langraph/warren_buffet_investement_principles.txt: -------------------------------------------------------------------------------- 1 | Value investing: Buffett looks for undervalued companies - those trading below their intrinsic value. He aims to buy great businesses at fair prices, rather than fair businesses at great prices. 2 | Long-term perspective: He invests with a long-term outlook, often holding stocks for decades. This aligns with his belief that the stock market is unpredictable in the short term but tends to rise over the long term. 3 | Understanding the business: Buffett only invests in companies and industries he thoroughly understands. This principle helps him better assess the company's potential and risks. 4 | Competitive advantage: He looks for companies with a strong "economic moat" - a sustainable competitive advantage that protects the company from competitors. 5 | Quality management: Buffett places high importance on honest, competent management teams that act in the best interests of shareholders. 6 | Financial health: He prefers companies with strong balance sheets, consistent earnings, high return on equity, and low debt. 7 | Predictable earnings: Buffett favors businesses with steady and predictable earnings rather than those in volatile or cyclical industries. 8 | Margin of safety: He always aims to buy stocks with a significant margin of safety - the difference between the intrinsic value of a stock and its market price. 9 | Dividend policy: While not a strict requirement, Buffett often favors companies that pay dividends and have a history of increasing them. 10 | Circle of competence: He sticks to investments within his "circle of competence" - areas where he has deep knowledge and expertise. -------------------------------------------------------------------------------- /benchmark_stock_analysis/summary/analyse.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import matplotlib.pyplot as plt 3 | import seaborn as sns 4 | 5 | # Read the CSV data 6 | df = pd.read_csv('framework_comparison.csv') 7 | 8 | # Set the style for the plots 9 | plt.style.use('seaborn') 10 | 11 | # Create a figure with subplots 12 | fig, axs = plt.subplots(2, 2, figsize=(20, 20)) 13 | fig.suptitle('AI Framework Comparison', fontsize=16) 14 | 15 | # 1. Cost and Total Tokens 16 | ax1 = axs[0, 0] 17 | ax1.bar(df['Framework'], df['Cost']) 18 | ax1.set_title('Cost per Run') 19 | ax1.set_ylabel('Cost ($)') 20 | ax1.tick_params(axis='x', rotation=45) 21 | 22 | ax1_twin = ax1.twinx() 23 | ax1_twin.plot(df['Framework'], df['Total Tokens'], 'r-o') 24 | ax1_twin.set_ylabel('Total Tokens', color='r') 25 | ax1_twin.tick_params(axis='y', labelcolor='r') 26 | 27 | # 2. Lines of Code Comparison 28 | ax2 = axs[0, 1] 29 | ax2.bar(df['Framework'], df['Lines of Code (Excluding Tool)'], label='Excluding Tool') 30 | ax2.bar(df['Framework'], df['Lines of Code (Tool Usage)'], bottom=df['Lines of Code (Excluding Tool)'], label='Tool Usage') 31 | ax2.set_title('Lines of Code Comparison') 32 | ax2.set_ylabel('Number of Lines') 33 | ax2.legend() 34 | ax2.tick_params(axis='x', rotation=45) 35 | 36 | # 3. Execution Time 37 | ax3 = axs[1, 0] 38 | ax3.bar(df['Framework'], df['Execution Time (s)']) 39 | ax3.set_title('Execution Time') 40 | ax3.set_ylabel('Time (seconds)') 41 | ax3.tick_params(axis='x', rotation=45) 42 | 43 | # 4. Ease of Use and Installation Complexity 44 | ax4 = axs[1, 1] 45 | ease_of_use_map = {'Easy': 1, 'Medium': 2, 'Hard': 3} 46 | installation_complexity_map = {'Low': 1, 'Medium': 2, 'High': 3} 47 | 48 | df['Ease of Use Numeric'] = df['Ease of Use'].map(ease_of_use_map) 49 | df['Installation Complexity Numeric'] = df['Installation Complexity'].map(installation_complexity_map) 50 | 51 | ax4.scatter(df['Ease of Use Numeric'], df['Installation Complexity Numeric'], s=100) 52 | for i, txt in enumerate(df['Framework']): 53 | ax4.annotate(txt, (df['Ease of Use Numeric'][i], df['Installation Complexity Numeric'][i]), xytext=(5,5), textcoords='offset points') 54 | 55 | ax4.set_xticks([1, 2, 3]) 56 | ax4.set_yticks([1, 2, 3]) 57 | ax4.set_xticklabels(['Easy', 'Medium', 'Hard']) 58 | ax4.set_yticklabels(['Low', 'Medium', 'High']) 59 | ax4.set_xlabel('Ease of Use') 60 | ax4.set_ylabel('Installation Complexity') 61 | ax4.set_title('Ease of Use vs Installation Complexity') 62 | 63 | plt.tight_layout() 64 | plt.savefig('framework_comparison.png') 65 | plt.show() -------------------------------------------------------------------------------- /benchmark_stock_analysis/summary/framework_comparison.csv: -------------------------------------------------------------------------------- 1 | Framework,Cost,Total Tokens,Lines of Code (Excluding Tool),Lines of Code (Tool Usage),Execution Time (s),Ease of Use,Installation Complexity 2 | AutoGen,0.00064075,3089,107,56,9.24,Easy,Low 3 | CrewAI,0.000684,5829,124,86,23.5,Medium,Medium 4 | LangGraph,0.00041935,1128.67,81,60,15.43,Hard,High 5 | Agent Zero,0.03773053,94326,0,0,94,Easy,High -------------------------------------------------------------------------------- /blog_writer.py: -------------------------------------------------------------------------------- 1 | # Install necessary libraries if running on your local machine 2 | # !pip install crewai==0.28.8 crewai_tools==0.1.6 langchain_community==0.0.29 3 | from keys import OPENAI_MODEL_NAME, OPENAI_API_KEY, GROQ_API_KEY 4 | 5 | from langchain_groq import ChatGroq 6 | 7 | # Warning control 8 | import warnings 9 | warnings.filterwarnings('ignore') 10 | 11 | # Import necessary libraries from crewAI 12 | from crewai import Agent, Task, Crew 13 | import os 14 | 15 | 16 | os.environ["OPENAI_MODEL_NAME"] = OPENAI_MODEL_NAME 17 | os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY 18 | os.environ["GROQ_API_KEY"] = GROQ_API_KEY 19 | 20 | GROQ_LLM = ChatGroq( 21 | # api_key=os.getenv("GROQ_API_KEY"), 22 | model="llama3-70b-8192" 23 | ) 24 | 25 | from IPython.display import Markdown 26 | 27 | # Define the Planner Agent 28 | planner = Agent( 29 | role="Content Planner", 30 | goal="Plan engaging and factually accurate content on {topic}", 31 | backstory=( 32 | "You're working on planning a blog article " 33 | "about the topic: {topic}. " 34 | "You collect information that helps the audience learn something " 35 | "and make informed decisions. " 36 | "Your work is the basis for the Content Writer to write an article on this topic." 37 | ), 38 | allow_delegation=False, 39 | llm = GROQ_LLM, 40 | verbose=True 41 | ) 42 | 43 | # Define the Writer Agent 44 | writer = Agent( 45 | role="Content Writer", 46 | goal="Write insightful and factually accurate opinion piece about the topic: {topic}", 47 | backstory=( 48 | "You're working on writing a new opinion piece about the topic: {topic}. " 49 | "You base your writing on the work of the Content Planner, who provides an outline " 50 | "and relevant context about the topic. " 51 | "You follow the main objectives and direction of the outline, as provided by the Content Planner. " 52 | "You also provide objective and impartial insights and back them up with information provided by the Content Planner. " 53 | "You acknowledge in your opinion piece when your statements are opinions as opposed to objective statements." 54 | ), 55 | allow_delegation=False, 56 | llm = GROQ_LLM, 57 | verbose=True 58 | ) 59 | 60 | # Define the Editor Agent 61 | editor = Agent( 62 | role="Editor", 63 | goal="Edit a given blog post to align with the writing style of the organization.", 64 | backstory=( 65 | "You are an editor who receives a blog post from the Content Writer. " 66 | "Your goal is to review the blog post to ensure that it follows journalistic best practices, " 67 | "provides balanced viewpoints when providing opinions or assertions, " 68 | "and also avoids major controversial topics or opinions when possible." 69 | ), 70 | allow_delegation=False, 71 | llm = GROQ_LLM, 72 | verbose=True 73 | ) 74 | 75 | # Define the Frontend Developer Agent specialized in UI/UX 76 | frontend_developer = Agent( 77 | role="Frontend Developer", 78 | goal="Develop a responsive and visually appealing blog post written in html on the topic: {topic}", 79 | backstory=( 80 | "You are a frontend developer working on creating a website for the blog post on {topic}. " 81 | "Your goal is to design a responsive and visually appealing blog post that showcases the content effectively and uses html " 82 | "You will work closely with the Content Planner and Content Writer to ensure that the website design aligns with the content and brand guidelines." 83 | ), 84 | allow_delegation=False, 85 | llm = GROQ_LLM, 86 | verbose=True 87 | ) 88 | 89 | # Define the Planning Task 90 | plan = Task( 91 | description=( 92 | "1. Prioritize the latest trends, key players, and noteworthy news on {topic}.\n" 93 | "2. Identify the target audience, considering their interests and pain points.\n" 94 | "3. Develop a detailed content outline including an introduction, key points, and a call to action.\n" 95 | "4. Include SEO keywords and relevant data or sources." 96 | ), 97 | expected_output="A comprehensive content plan document with an outline, audience analysis, SEO keywords, and resources.", 98 | agent=planner, 99 | ) 100 | 101 | # Define the Writing Task 102 | write = Task( 103 | description=( 104 | "1. Use the content plan to craft a compelling blog post on {topic}.\n" 105 | "2. Incorporate SEO keywords naturally.\n" 106 | "3. Sections/Subtitles are properly named in an engaging manner.\n" 107 | "4. Ensure the post is structured with an engaging introduction, insightful body, and a summarizing conclusion.\n" 108 | "5. Proofread for grammatical errors and alignment with the brand's voice." 109 | ), 110 | expected_output="A well-written blog post in html format, ready for publication, each section should have 2 or 3 paragraphs.", 111 | agent=writer, 112 | ) 113 | 114 | # Define the Editing Task 115 | edit = Task( 116 | description=("Proofread the given blog post for grammatical errors and alignment with the brand's voice."), 117 | expected_output="A well-written blog post in html format, ready for publication, each section should have 2 or 3 paragraphs.", 118 | agent=editor 119 | ) 120 | 121 | # Define the Frontend Development Task 122 | edit_html = Task( 123 | description=( 124 | "1. Design a responsive and visually appealing blog post in html format.\n" 125 | "2. Ensure the blog post is user-friendly and accessible.\n" 126 | "3. Make the blog post nice and visually appealing. following the ui/ux best practises\n" 127 | "4. The blog post should be responsive and work on all devices.\n" 128 | "6. The blog post should be centered and have a good font size.\n" 129 | "7 Use css to style the blog post, make it visually appealing.\n" 130 | "8. Dont add a navigation bar, just the blog post, dont add any buttons for now \n" 131 | "9. Add a header image with the given image_url: {image_url} to the blog post, make it visually appealing.\n" 132 | "10. Take care that the blog post is really centered' \n" 133 | 134 | ), 135 | expected_output="A responsive and visually appealing blog post in html format, ready for deployment.", 136 | agent=frontend_developer, 137 | output_file="videos/video4/version_4.html" 138 | ) 139 | 140 | # Create the Crew 141 | crew = Crew( 142 | agents=[planner, writer, editor, frontend_developer], 143 | tasks=[plan, write, edit, edit_html], 144 | verbose=2 145 | ) 146 | 147 | inputs = { 148 | "topic": "AI Agents", 149 | "image_url" : "https://images.unsplash.com/photo-1461988320302-91bde64fc8e4?ixid=2yJhcHBfaWQiOjEyMDd9&&fm=jpg&w=400&fit=max" 150 | } 151 | 152 | # Running the Crew with a sample topic 153 | result = crew.kickoff(inputs=inputs) 154 | 155 | # Display the results as markdown in the notebook 156 | Markdown(result) 157 | 158 | # Try it Yourself with a different topic 159 | # topic = "YOUR TOPIC HERE" 160 | # result = crew.kickoff(inputs={"topic": topic}) 161 | 162 | # Markdown(result) 163 | 164 | print(crew.usage_metrics) -------------------------------------------------------------------------------- /dev_habit_tracker/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import { View, StyleSheet, TouchableOpacity, SafeAreaView, StatusBar } from 'react-native'; 3 | import AsyncStorage from '@react-native-async-storage/async-storage'; 4 | import { Ionicons } from '@expo/vector-icons'; 5 | import CalendarView from '@/components/views/CalendarView'; 6 | import HabitView from '@/components/views/HabitView'; 7 | import EditView from '@/components/views/EditView'; 8 | 9 | interface Habit { 10 | id: string; 11 | name: string; 12 | description: string; 13 | } 14 | 15 | type HabitLogs = { 16 | [date: string]: { 17 | [habitId: string]: boolean; 18 | }; 19 | }; 20 | 21 | const defaultData: { habits: Habit[], habitLogs: HabitLogs } = { 22 | habits: [ 23 | { 24 | id: "1", 25 | name: "Drink water", 26 | description: "Drink 8 glasses of water daily" 27 | }, 28 | { 29 | id: "2", 30 | name: "Exercise", 31 | description: "30 minutes of physical activity" 32 | }, 33 | { 34 | id: "3", 35 | name: "Read", 36 | description: "Read for 20 minutes before bed" 37 | } 38 | ], 39 | habitLogs: { 40 | "2024-08-23": { 41 | "1": true, 42 | "2": false, 43 | "3": true 44 | }, 45 | "2024-08-24": { 46 | "1": true, 47 | "2": true, 48 | "3": false 49 | }, 50 | "2024-08-25": { 51 | "1": false, 52 | "2": true, 53 | "3": true 54 | } 55 | } 56 | }; 57 | 58 | export default function App() { 59 | const [habits, setHabits] = useState(defaultData.habits); 60 | const [habitLogs, setHabitLogs] = useState(defaultData.habitLogs); 61 | const [selectedDate, setSelectedDate] = useState(new Date()); 62 | const [editModalVisible, setEditModalVisible] = useState(false); 63 | const [editingHabit, setEditingHabit] = useState(undefined); 64 | 65 | useEffect(() => { 66 | const loadData = async () => { 67 | try { 68 | const storedHabits = await AsyncStorage.getItem('habits'); 69 | const storedLogs = await AsyncStorage.getItem('habitLogs'); 70 | 71 | if (storedHabits && storedLogs) { 72 | setHabits(JSON.parse(storedHabits)); 73 | setHabitLogs(JSON.parse(storedLogs)); 74 | } else { 75 | await AsyncStorage.setItem('habits', JSON.stringify(defaultData.habits)); 76 | await AsyncStorage.setItem('habitLogs', JSON.stringify(defaultData.habitLogs)); 77 | } 78 | } catch (error) { 79 | console.error('Error loading data:', error); 80 | } 81 | }; 82 | 83 | loadData(); 84 | }, []); 85 | 86 | const handleToggleHabit = (habitId: string) => { 87 | const dateKey = selectedDate.toISOString().split('T')[0]; 88 | setHabitLogs(prevLogs => { 89 | const updatedLogs = { ...prevLogs }; 90 | if (!updatedLogs[dateKey]) { 91 | updatedLogs[dateKey] = {}; 92 | } 93 | updatedLogs[dateKey] = { 94 | ...updatedLogs[dateKey], 95 | [habitId]: !updatedLogs[dateKey][habitId] 96 | }; 97 | AsyncStorage.setItem('habitLogs', JSON.stringify(updatedLogs)).catch(error => 98 | console.error('Error saving habit logs:', error) 99 | ); 100 | return updatedLogs; 101 | }); 102 | }; 103 | 104 | const handleEditHabit = (habit: Habit) => { 105 | setEditingHabit(habit); 106 | setEditModalVisible(true); 107 | }; 108 | 109 | const handleAddHabit = () => { 110 | setEditingHabit(undefined); 111 | setEditModalVisible(true); 112 | }; 113 | 114 | const handleSaveHabit = (savedHabit: Habit) => { 115 | setHabits(prevHabits => { 116 | const newHabits = editingHabit 117 | ? prevHabits.map(h => h.id === savedHabit.id ? savedHabit : h) 118 | : [...prevHabits, savedHabit]; 119 | AsyncStorage.setItem('habits', JSON.stringify(newHabits)).catch(error => 120 | console.error('Error saving habits:', error) 121 | ); 122 | return newHabits; 123 | }); 124 | }; 125 | 126 | return ( 127 | 128 | 129 | 130 | 131 | 138 | 139 | 140 | 141 | 142 | setEditModalVisible(false)} 145 | onSave={handleSaveHabit} 146 | habit={editingHabit} 147 | /> 148 | 149 | ); 150 | } 151 | 152 | const styles = StyleSheet.create({ 153 | safeArea: { 154 | flex: 1, 155 | backgroundColor: '#f0f8ff', 156 | }, 157 | container: { 158 | flex: 1, 159 | backgroundColor: '#ffffff', 160 | }, 161 | addButton: { 162 | position: 'absolute', 163 | right: 20, 164 | bottom: 20, 165 | backgroundColor: '#4a90e2', 166 | width: 56, 167 | height: 56, 168 | borderRadius: 28, 169 | justifyContent: 'center', 170 | alignItems: 'center', 171 | elevation: 5, 172 | shadowColor: '#000', 173 | shadowOffset: { width: 0, height: 2 }, 174 | shadowOpacity: 0.25, 175 | shadowRadius: 3.84, 176 | }, 177 | }); -------------------------------------------------------------------------------- /dev_habit_tracker/prompt.txt: -------------------------------------------------------------------------------- 1 | ## Prompts 2 | 3 | You are an experienced React Native developer tasked with creating a habit tracker app using React Native and Expo. Your first task is to create the overall UI structure in index.tsx with placeholders for CalendarView and HabitView. 4 | 5 | I will provide you with a concept for the habit tracker app. Your job is to carefully analyze this concept and then create the code for index.tsx based on the requirements. 6 | 7 | Here's the concept for the habit tracker app: 8 | {{CONCEPT}} 9 | 10 | Please follow these steps: 11 | 12 | 1. Carefully read and analyze the provided concept. 13 | 2. Identify the key components and features that need to be included in the overall UI structure. 14 | 3. Create the code for index.tsx, which should include: a. Necessary imports (React, React Native components, etc.) b. A main App component c. Placeholders for CalendarView and HabitView d. Basic styling to arrange the components 15 | 16 | Requirements for index.tsx: 17 | 18 | - Use functional components and hooks 19 | - Import necessary components from react-native 20 | - Create a placeholder CalendarView component 21 | - Create a placeholder HabitView component 22 | - Implement a basic layout that includes both CalendarView and HabitView 23 | - Use StyleSheet to define styles for the components 24 | 25 | Remember to focus only on creating the overall UI structure in index.tsx with placeholders for CalendarView and HabitView. Do not implement the full functionality of these components at this stage. 26 | 27 | After creating the index.tsx file, please provide clear step-by-step instructions for setting up Expo and previewing the app on my {{phone}}. Include details on: 28 | 29 | - Ensuring Node.js is installed as a prerequisite 30 | - Using the command `npx create-expo-app@latest` to install Expo and create the project 31 | - Configuring the Expo project 32 | - Running the app on the development server 33 | - Installing and using the Expo Go app on my {{phone}} 34 | - Connecting the {{phone}} to view and test the app 35 | - Any specific considerations for my {{phone}} model 36 | 37 | Make sure the instructions begin with checking for Node.js installation and use the specified `npx create-expo-app@latest` command. The instructions should be concise, easy to follow, and tailored to my {{phone}} if there are any model-specific steps. 38 | 39 | Phone: 40 | iphone 41 | 42 | Concept: 43 | 44 | ## Habit Tracker App Concept 45 | 46 | ### Project Structure 47 | 48 | - index.tsx: Entry point of the app (in the root directory) 49 | - @/components/views/CalendarView.js: Calendar strip component 50 | - @/components/views/HabitView.js: Habit list component 51 | - @/components/views/EditView.js: Habit editing component 52 | - defaultData.json: Contains initial demo data for the app 53 | 54 | ### Main Components 55 | 56 | - CalendarView: Display the days of the week at the top 57 | - HabitView: Show individual habit items below the calendar 58 | - EditView: Modal view for editing habit details 59 | 60 | ### Data Structure 61 | 62 | - Store habits as an array of objects: [{id, name, description, isDone}] 63 | - Store habit logs as an object with dates as keys and habit completion status as values 64 | 65 | ### State Management 66 | 67 | - Use React's useState in index.tsx to manage the habit list, habit logs, and selected date 68 | - Pass necessary data and functions as props to child components 69 | 70 | ### User Interactions 71 | 72 | - Add new habits via a simple modal or form in HabitView 73 | - Edit existing habits through the EditView modal 74 | - Toggle habit completion status in HabitView 75 | - Tap on a day in CalendarView to focus on that day and display corresponding habit states 76 | 77 | ### Styling 78 | 79 | - Include styling code within each component file (CalendarView.js, HabitView.js, EditView.js) 80 | - Use Expo Elements for consistent, attractive UI components 81 | - Implement a light theme with pastel blues for habit backgrounds 82 | - Use distinct visual indicators for completed and uncompleted habits (e.g., checkmarks, color changes) 83 | 84 | ### Data Persistence 85 | 86 | - Use AsyncStorage to save and retrieve the habit list and habit logs 87 | 88 | ### Implementation Details 89 | 90 | - index.tsx: 91 | - Manages state and data flow 92 | - Renders CalendarView and HabitView 93 | - Initializes app with demo data if no existing data is found 94 | - Manages selected date state 95 | - components/views/CalendarView.js: 96 | - Horizontal scrollable view for days of the week 97 | - Highlight current day and selected day 98 | - Allows navigation to previous days 99 | - Includes its own styling code 100 | - components/views/HabitView.js: 101 | - Renders list of habits 102 | - Displays habit completion status for the selected day 103 | - Includes "Add Habit" functionality 104 | - Allows toggling habit completion status with clear visual feedback 105 | - Provides an edit button for each habit 106 | - Includes its own styling code 107 | - components/views/EditView.js: 108 | - Modal view for editing habit details 109 | - Allows changing habit name and description 110 | - Includes its own styling code 111 | 112 | ### Key Expo Features to Use 113 | 114 | - Expo Elements for UI components 115 | - Expo Vector Icons for simple icons (e.g., edit button, completion status) 116 | - AsyncStorage for data persistence 117 | 118 | ### Demo Data and Functionality 119 | 120 | - Include a defaultData.json file with: 121 | - 3 predefined habits: "Drink water", "Exercise", and "Read" 122 | - Habit logs for the previous three days 123 | - On first launch, load the demo data into AsyncStorage 124 | - Allow users to interact with the demo data immediately: 125 | - View predefined habits 126 | - See completion status for the past three days 127 | - Add new habits 128 | - Edit existing habits 129 | - Toggle habit completion status for any day 130 | - Provide a visual distinction between demo data and user-added data (e.g., different background color) 131 | 132 | ### Habit Editing and Completion 133 | 134 | - Each habit in HabitView has an edit button that opens the EditView modal 135 | - EditView allows users to modify the habit name and description and delete it 136 | - In HabitView, each habit has a clear visual indicator of its completion status (e.g., checkbox, toggle switch) 137 | - Tapping on the completion indicator toggles the habit's status for the selected day 138 | - Use distinct visual styles for completed and uncompleted habits (e.g., different colors, opacity) 139 | 140 | ### Calendar Navigation and Historical Data 141 | 142 | - Users can navigate to previous days using the CalendarView 143 | - When a past date is selected, HabitView updates to show the habit completion status for that specific day 144 | - Habits in HabitView reflect the correct completion status based on the selected date 145 | 146 | ### Demo Data to use 147 | 148 | { 149 | "habits": [ 150 | { 151 | "id": "1", 152 | "name": "Drink water", 153 | "description": "Drink 8 glasses of water daily" 154 | }, 155 | { 156 | "id": "2", 157 | "name": "Exercise", 158 | "description": "30 minutes of physical activity" 159 | }, 160 | { 161 | "id": "3", 162 | "name": "Read", 163 | "description": "Read for 20 minutes before bed" 164 | } 165 | ], 166 | "habitLogs": { 167 | "2024-08-23": { 168 | "1": true, 169 | "2": false, 170 | "3": true 171 | }, 172 | "2024-08-24": { 173 | "1": true, 174 | "2": true, 175 | "3": false 176 | }, 177 | "2024-08-25": { 178 | "1": false, 179 | "2": true, 180 | "3": true 181 | } 182 | } 183 | } -------------------------------------------------------------------------------- /dev_habit_tracker/views/CalendarView.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { View, Text, StyleSheet, ScrollView, TouchableOpacity } from 'react-native'; 3 | 4 | interface CalendarViewProps { 5 | selectedDate: Date; 6 | onSelectDate: (date: Date) => void; 7 | } 8 | 9 | const CalendarView: React.FC = ({ selectedDate, onSelectDate }) => { 10 | const generateDates = (startDate: Date, numDays: number) => { 11 | const dates = []; 12 | for (let i = 0; i < numDays; i++) { 13 | const date = new Date(startDate); 14 | date.setDate(startDate.getDate() - i); 15 | dates.push(date); 16 | } 17 | return dates.reverse(); 18 | }; 19 | 20 | const dates = generateDates(new Date(), 7); 21 | 22 | const isToday = (date: Date) => { 23 | const today = new Date(); 24 | return date.getDate() === today.getDate() && 25 | date.getMonth() === today.getMonth() && 26 | date.getFullYear() === today.getFullYear(); 27 | }; 28 | 29 | const isSelected = (date: Date) => { 30 | return date.getDate() === selectedDate.getDate() && 31 | date.getMonth() === selectedDate.getMonth() && 32 | date.getFullYear() === selectedDate.getFullYear(); 33 | }; 34 | 35 | return ( 36 | 37 | 38 | {dates.map((date, index) => ( 39 | onSelectDate(date)} 47 | > 48 | 49 | {date.toLocaleString('default', { weekday: 'short' })} 50 | 51 | 52 | {date.getDate()} 53 | 54 | 55 | ))} 56 | 57 | 58 | ); 59 | }; 60 | 61 | const styles = StyleSheet.create({ 62 | container: { 63 | backgroundColor: '#f0f8ff', 64 | paddingVertical: 20, 65 | }, 66 | scrollView: { 67 | paddingHorizontal: 10, 68 | }, 69 | dateContainer: { 70 | width: 60, 71 | height: 80, 72 | justifyContent: 'center', 73 | alignItems: 'center', 74 | marginHorizontal: 5, 75 | borderRadius: 15, 76 | backgroundColor: '#ffffff', 77 | shadowColor: '#000', 78 | shadowOffset: { width: 0, height: 1 }, 79 | shadowOpacity: 0.2, 80 | shadowRadius: 2, 81 | elevation: 3, 82 | }, 83 | selectedDate: { 84 | backgroundColor: '#4a90e2', 85 | }, 86 | today: { 87 | borderColor: '#4a90e2', 88 | borderWidth: 2, 89 | }, 90 | dayText: { 91 | fontSize: 14, 92 | color: '#666', 93 | marginBottom: 5, 94 | }, 95 | dateText: { 96 | fontSize: 20, 97 | fontWeight: 'bold', 98 | color: '#333', 99 | }, 100 | selectedText: { 101 | color: '#ffffff', 102 | }, 103 | }); 104 | 105 | export default CalendarView; -------------------------------------------------------------------------------- /dev_habit_tracker/views/EditView.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import { View, Text, TextInput, StyleSheet, TouchableOpacity, Modal } from 'react-native'; 3 | 4 | interface Habit { 5 | id: string; 6 | name: string; 7 | description: string; 8 | } 9 | 10 | interface EditViewProps { 11 | visible: boolean; 12 | onClose: () => void; 13 | onSave: (habit: Habit) => void; 14 | habit?: Habit; 15 | } 16 | 17 | const EditView: React.FC = ({ visible, onClose, onSave, habit }) => { 18 | const [name, setName] = useState(''); 19 | const [description, setDescription] = useState(''); 20 | 21 | useEffect(() => { 22 | if (habit) { 23 | setName(habit.name); 24 | setDescription(habit.description); 25 | } else { 26 | setName(''); 27 | setDescription(''); 28 | } 29 | }, [habit]); 30 | 31 | const handleSave = () => { 32 | if (name.trim()) { 33 | onSave({ 34 | id: habit ? habit.id : Date.now().toString(), 35 | name: name.trim(), 36 | description: description.trim() 37 | }); 38 | onClose(); 39 | } 40 | }; 41 | 42 | return ( 43 | 49 | 50 | 51 | {habit ? 'Edit Habit' : 'Add New Habit'} 52 | 58 | 65 | 66 | 67 | Cancel 68 | 69 | 70 | Save 71 | 72 | 73 | 74 | 75 | 76 | ); 77 | }; 78 | 79 | const styles = StyleSheet.create({ 80 | centeredView: { 81 | flex: 1, 82 | justifyContent: 'center', 83 | alignItems: 'center', 84 | backgroundColor: 'rgba(0, 0, 0, 0.5)', 85 | }, 86 | modalView: { 87 | backgroundColor: 'white', 88 | borderRadius: 20, 89 | padding: 35, 90 | alignItems: 'center', 91 | shadowColor: '#000', 92 | shadowOffset: { 93 | width: 0, 94 | height: 2 95 | }, 96 | shadowOpacity: 0.25, 97 | shadowRadius: 4, 98 | elevation: 5, 99 | width: '80%', 100 | }, 101 | modalTitle: { 102 | fontSize: 20, 103 | fontWeight: 'bold', 104 | marginBottom: 15, 105 | }, 106 | input: { 107 | height: 40, 108 | borderColor: 'gray', 109 | borderWidth: 1, 110 | borderRadius: 5, 111 | width: '100%', 112 | marginBottom: 15, 113 | paddingHorizontal: 10, 114 | }, 115 | descriptionInput: { 116 | height: 80, 117 | textAlignVertical: 'top', 118 | }, 119 | buttonContainer: { 120 | flexDirection: 'row', 121 | justifyContent: 'space-between', 122 | width: '100%', 123 | }, 124 | button: { 125 | borderRadius: 5, 126 | padding: 10, 127 | elevation: 2, 128 | width: '45%', 129 | }, 130 | cancelButton: { 131 | backgroundColor: '#F194FF', 132 | }, 133 | saveButton: { 134 | backgroundColor: '#2196F3', 135 | }, 136 | buttonText: { 137 | color: 'white', 138 | fontWeight: 'bold', 139 | textAlign: 'center', 140 | }, 141 | }); 142 | 143 | export default EditView; -------------------------------------------------------------------------------- /dev_habit_tracker/views/HabitView.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { View, Text, StyleSheet, FlatList, TouchableOpacity } from 'react-native'; 3 | import { Ionicons } from '@expo/vector-icons'; 4 | 5 | interface Habit { 6 | id: string; 7 | name: string; 8 | description: string; 9 | } 10 | 11 | interface HabitViewProps { 12 | habits: Habit[]; 13 | habitLogs: Record>; 14 | selectedDate: Date; 15 | onToggleHabit: (habitId: string) => void; 16 | onEditHabit: (habit: Habit) => void; 17 | } 18 | 19 | const HabitView: React.FC = ({ 20 | habits, 21 | habitLogs, 22 | selectedDate, 23 | onToggleHabit, 24 | onEditHabit 25 | }) => { 26 | const formatDate = (date: Date) => { 27 | return date.toISOString().split('T')[0]; 28 | }; 29 | 30 | const renderHabitItem = ({ item }: { item: Habit }) => { 31 | const isCompleted = habitLogs[formatDate(selectedDate)]?.[item.id] || false; 32 | 33 | return ( 34 | 35 | onToggleHabit(item.id)} 38 | > 39 | {isCompleted && } 40 | 41 | 42 | {item.name} 43 | {item.description} 44 | 45 | onEditHabit(item)} 48 | > 49 | 50 | 51 | 52 | ); 53 | }; 54 | 55 | return ( 56 | item.id} 60 | style={styles.container} 61 | /> 62 | ); 63 | }; 64 | 65 | const styles = StyleSheet.create({ 66 | container: { 67 | flex: 1, 68 | backgroundColor: '#ffffff', 69 | }, 70 | habitItem: { 71 | flexDirection: 'row', 72 | alignItems: 'center', 73 | padding: 15, 74 | borderBottomWidth: 1, 75 | borderBottomColor: '#f0f0f0', 76 | }, 77 | checkbox: { 78 | width: 28, 79 | height: 28, 80 | borderWidth: 2, 81 | borderColor: '#4a90e2', 82 | borderRadius: 14, 83 | justifyContent: 'center', 84 | alignItems: 'center', 85 | marginRight: 15, 86 | }, 87 | checkboxCompleted: { 88 | backgroundColor: '#4a90e2', 89 | }, 90 | habitInfo: { 91 | flex: 1, 92 | }, 93 | habitName: { 94 | fontSize: 16, 95 | fontWeight: 'bold', 96 | color: '#333', 97 | marginBottom: 4, 98 | }, 99 | habitDescription: { 100 | fontSize: 14, 101 | color: '#666', 102 | }, 103 | editButton: { 104 | padding: 5, 105 | }, 106 | }); 107 | 108 | export default HabitView; -------------------------------------------------------------------------------- /lead_scraper/autogen/autogen_lead_scraper.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, Any, List, Optional 2 | import os 3 | import sys 4 | import time 5 | from dotenv import load_dotenv 6 | import asyncio 7 | from uuid import uuid4 8 | import json 9 | import re 10 | import dotenv 11 | sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "../../../../"))) 12 | dotenv.load_dotenv() 13 | 14 | load_dotenv() 15 | 16 | # Add the project root to the Python path 17 | 18 | from autogen_agentchat.agents import AssistantAgent 19 | from autogen_ext.models.openai import OpenAIChatCompletionClient 20 | from src.workflows.lead_scraper.tools.scraper import scrape_website 21 | from autogen_agentchat.teams import RoundRobinGroupChat 22 | from pydantic import BaseModel 23 | from autogen_core.tools import FunctionTool 24 | 25 | class WebsiteInformation(BaseModel): 26 | decision_maker_name: Optional[str] = None 27 | phone_number: Optional[str] = None 28 | email: Optional[str] = None 29 | impressum_url: Optional[str] = None 30 | company_industry: Optional[str] = None 31 | contact_url: Optional[str] = None 32 | company_products: Optional[List[str]] = None 33 | content_summary_points: Optional[List[str]] = None 34 | 35 | 36 | async def scrape_website_tool(url: str) -> str: 37 | """Get the content from a website URL.""" 38 | print(f"Scraping website: {url}") 39 | content = await scrape_website(url) 40 | print(f"Website scraped successfully") 41 | return content 42 | 43 | 44 | class AutogenLeadScraper: 45 | def __init__(self, input_data: Dict[str, Any]): 46 | """ 47 | Initialize the AutogenLeadScraper for a single website. 48 | 49 | Args: 50 | input_data: Dictionary containing workflow configuration and input data 51 | """ 52 | self.input_data = input_data 53 | self.website_url = input_data["workflow_input_data"]["domain_url"] 54 | self.record_id = uuid4() 55 | 56 | # Initialize the model client 57 | 58 | 59 | def parse_json_response(self, response_content): 60 | """Parse JSON response from the agent.""" 61 | # Extract JSON string from the response if needed 62 | json_match = re.search(r'```json\s*(.*?)\s*```', response_content, re.DOTALL) 63 | if json_match: 64 | json_str = json_match.group(1) 65 | else: 66 | json_str = response_content 67 | 68 | try: 69 | response_dict = json.loads(json_str) 70 | return response_dict 71 | except json.JSONDecodeError as e: 72 | print(f"Failed to parse JSON: {e}") 73 | print(f"Raw content: {response_content}") 74 | return {} 75 | 76 | async def run(self) -> Dict[str, Any]: 77 | """ 78 | Run the lead scraper for a single website and return the result. 79 | 80 | Returns: 81 | The Autogen chat result object, potentially augmented with execution time. 82 | """ 83 | 84 | product_text = self.input_data["workflow_input_data"]["product_txt"] 85 | 86 | model_client_scraper = OpenAIChatCompletionClient( 87 | model=self.input_data["model"], 88 | response_format=WebsiteInformation 89 | ) 90 | 91 | web_search_tool = FunctionTool( 92 | scrape_website_tool, 93 | description="Search the web for information", 94 | strict=True 95 | ) 96 | 97 | # Create the assistant agent with tools 98 | scrape_agent_root_url = AssistantAgent( 99 | name="lead_scraper_assistant_root_url", 100 | system_message="""You are an expert web scraper agent specializing in 101 | find the contact information on the root url 102 | """, 103 | description=""" 104 | """, 105 | model_client=model_client_scraper, 106 | tools=[web_search_tool], 107 | reflect_on_tool_use=True, 108 | ) 109 | scrape_agent_contact = AssistantAgent( 110 | name="lead_scraper_assistant_contact", 111 | system_message="""You are an expert web scraper agent specializing in 112 | you use the impressum_url and the contact_url to find all required contact information 113 | """, 114 | description=""" 115 | """, 116 | model_client=model_client_scraper, 117 | tools=[web_search_tool], 118 | reflect_on_tool_use=True, 119 | ) 120 | 121 | # Create the task message 122 | # task = f"""Return me the email data for the url: {self.website_url}: 123 | # """ 124 | task = f"""find me all necessary website information for the url: {self.website_url} 125 | """ 126 | 127 | # team = RoundRobinGroupChat([scrape_ragent, email_writer_agent], max_turns=2) 128 | # team = RoundRobinGroupChat([scrape_agent_root_url, scrape_agent_impressum], max_turns=2) 129 | team = RoundRobinGroupChat([scrape_agent_root_url, scrape_agent_contact], max_turns=2) 130 | 131 | # Record start time 132 | start_time = time.time() 133 | 134 | result = await team.run(task=task) 135 | 136 | # Record end time 137 | end_time = time.time() 138 | execution_time_seconds = end_time - start_time 139 | 140 | # Attach execution time to the result object 141 | # Assuming the result object allows adding arbitrary attributes 142 | try: 143 | setattr(result, 'execution_time_seconds', execution_time_seconds) 144 | except AttributeError: 145 | # As a fallback, maybe add it to the summary dict if it exists? 146 | if hasattr(result, 'summary') and isinstance(result.summary, dict): 147 | result.summary['execution_time_seconds'] = execution_time_seconds 148 | 149 | return result 150 | 151 | if __name__ == "__main__": 152 | # Define input data 153 | new_input_data = { 154 | "workflow": "lead_scraper", 155 | "model": "gpt-4o-mini", 156 | "framework": "autogen", 157 | "llm_provider": "openai", 158 | "workflow_input_data": { 159 | "product_txt": "Custom Wall Art/Canvas Prints", 160 | # "domain_url": "https://www.der-friseur-freiberg.de/impressum.php" 161 | # "domain_url": "https://www.der-friseur-freiberg.de/" 162 | "domain_url": "https://rang-und-namen.de/" 163 | # "domain_url": "https://www.themarfaspirit.com/" 164 | } 165 | } 166 | 167 | # Create and run the scraper 168 | start_time = time.time() 169 | scraper = AutogenLeadScraper(input_data=new_input_data) 170 | result = asyncio.run(scraper.run()) 171 | last_message = result.messages[-1] 172 | result_json = last_message.content 173 | messages = result.messages 174 | prompt_tokens = 0 175 | completion_tokens = 0 176 | 177 | # Extract token usage from all messages 178 | for message in messages: 179 | if hasattr(message, 'models_usage') and message.models_usage: 180 | usage = message.models_usage 181 | if isinstance(usage, dict): 182 | completion_tokens += usage.get('completion_tokens', 0) 183 | recent_completion_tokens = usage.get('completion_tokens', 0) 184 | prompt_tokens += usage.get('prompt_tokens', 0) 185 | recent_prompt_tokens = usage.get('prompt_tokens', 0) 186 | elif hasattr(usage, 'completion_tokens') and hasattr(usage, 'prompt_tokens'): 187 | completion_tokens += usage.completion_tokens 188 | prompt_tokens += usage.prompt_tokens 189 | 190 | website_url = new_input_data["workflow_input_data"]["domain_url"] 191 | print(f"Prompt tokens: {prompt_tokens}") 192 | print(f"Completion tokens: {completion_tokens}") 193 | print(f"Successfully processed {website_url}") 194 | print(result_json) 195 | end_time = time.time() 196 | print(f"Time taken: {end_time - start_time:.2f} seconds") 197 | -------------------------------------------------------------------------------- /lead_scraper/crewai/crewai_lead_scraper.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | from crewai import Agent, Task, Crew, Process, LLM 4 | from src.workflows.lead_scraper.tools.scraper import scrape_website 5 | from crewai.tools import tool 6 | import asyncio 7 | from dotenv import load_dotenv 8 | import json 9 | import time 10 | from pydantic import BaseModel 11 | from typing import Dict, Any, List, Optional 12 | from uuid import uuid4 13 | 14 | load_dotenv() 15 | 16 | @tool 17 | def extract_content_from_website(url: str) -> str: 18 | """ 19 | Extracts content from a website 20 | returns a markdown formatted string with well structured urls 21 | """ 22 | print(f"Scraping website: {url}") 23 | content = asyncio.run(scrape_website(url)) 24 | print(f"Website scraped successfully") 25 | return content 26 | 27 | # Pydantic models to parse the JSON returned by each task 28 | 29 | class WebsiteInformation(BaseModel): 30 | contact_url: Optional[str] = None 31 | impressum_url: Optional[str] = None 32 | decision_maker_name: Optional[str] = None 33 | phone_number: Optional[str] = None 34 | email: Optional[str] = None 35 | company_industry: Optional[str] = None 36 | company_products: Optional[List[str]] = None 37 | content_summary_points: Optional[List[str]] = None 38 | 39 | class CrewAiLeadScraper: 40 | def __init__(self, input_data: Dict[str, Any]): 41 | """ 42 | Initialize the CrewAiLeadScraper for a single website. 43 | 44 | Args: 45 | input_data: Dictionary containing workflow configuration and input data 46 | """ 47 | self.input_data = input_data 48 | self.website_url = input_data["workflow_input_data"]["domain_url"] 49 | self.product_text = input_data["workflow_input_data"]["product_txt"] 50 | self.record_id = uuid4() 51 | 52 | # Initialize LLM 53 | self.llm = LLM( 54 | model=input_data["model"] 55 | ) 56 | 57 | def run(self) -> Dict[str, Any]: 58 | """ 59 | Run the lead scraper for a single website. 60 | 61 | Returns: 62 | Dictionary with the result data 63 | """ 64 | print(f"\nProcessing {self.website_url}...") 65 | 66 | # Create the scraper agent 67 | scrape_agent = Agent( 68 | role='Web Scraper Agent', 69 | goal='find the required website information', 70 | backstory="""You are an expert web scraper agent specializing in 71 | finding website information""", 72 | allow_delegation=False, 73 | tools=[extract_content_from_website], 74 | llm=self.llm 75 | ) 76 | 77 | # Create the scrape task 78 | scrape_root_url_task = Task( 79 | description=f""" 80 | find the contact information on the root url : {self.website_url} 81 | """, 82 | expected_output="a well structured json object", 83 | agent=scrape_agent, 84 | output_json=WebsiteInformation 85 | ) 86 | 87 | print(f"Writing email for {self.website_url}") 88 | 89 | # Create the email task 90 | scrape_contact_task = Task( 91 | description=f""" 92 | find the contact information based on the impressum_url and the contact_url 93 | """, 94 | expected_output="a well structured json object", 95 | agent=scrape_agent, 96 | context=[scrape_root_url_task], 97 | output_json=WebsiteInformation 98 | ) 99 | 100 | # Create and run the crew 101 | crew = Crew( 102 | # agents=[scraper_agent, email_writer_agent], 103 | agents=[scrape_agent], 104 | tasks=[scrape_root_url_task, scrape_contact_task], 105 | verbose=False, 106 | process=Process.sequential 107 | ) 108 | 109 | # Kick off the crew and get the result 110 | crew_result = crew.kickoff() 111 | 112 | print(f"Successfully processed {self.website_url}") 113 | 114 | return crew_result 115 | 116 | if __name__ == "__main__": 117 | # Define input data 118 | new_input_data = { 119 | "workflow": "lead_scraper", 120 | "model": "gpt-4o-mini", 121 | "framework": "crewai", 122 | "llm_provider": "openai", 123 | "workflow_input_data": { 124 | "product_txt": "Custom Wall Art/Canvas Prints", 125 | "domain_url": "https://www.der-friseur-freiberg.de/" 126 | } 127 | } 128 | 129 | # Create and run the scraper 130 | start_time = time.time() 131 | scraper = CrewAiLeadScraper(input_data=new_input_data) 132 | result = scraper.run() 133 | result_json = json.dumps(result.json, indent=4) 134 | print(f"Result: {result}") 135 | end_time = time.time() 136 | print(f"Time taken: {end_time - start_time:.2f} seconds") -------------------------------------------------------------------------------- /lead_scraper/requirements.txt: -------------------------------------------------------------------------------- 1 | pydantic 2 | dotenv 3 | playwright 4 | 5 | #agent related 6 | crewai 7 | crewai[tools] 8 | 9 | # not agent related 10 | supabase 11 | fastapi 12 | 13 | #conflicting packages need to be installed manually 14 | #autogen-agentchat 0.5.1 15 | #autogen-ext[openai] 16 | #crawl4ai 0.5.0.post8 17 | 18 | #eg: pip install autogen-agentchat==0.5.1 autogen-ext[openai] 19 | 20 | -------------------------------------------------------------------------------- /lead_scraper/tools/scraper.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | from crawl4ai import AsyncWebCrawler, BrowserConfig 4 | 5 | browser_conf = BrowserConfig( 6 | browser_type="chrome", 7 | headless=True, 8 | text_mode=True, 9 | ) 10 | 11 | async def scrape_website(url): 12 | """Asynchronously scrape a website and return the content as markdown.""" 13 | async with AsyncWebCrawler(config=browser_conf) as crawler: 14 | result = await crawler.arun( 15 | url=url, 16 | ) 17 | # print(result.markdown) 18 | # store the result in experiment/crawl_step_1_output.txt 19 | # with open(output_file, "w") as f: 20 | # f.write(result.markdown) 21 | return result.markdown 22 | 23 | if __name__ == "__main__": 24 | asyncio.run(scrape_website("https://www.rang-und-namen.de/")) -------------------------------------------------------------------------------- /meal_planner/dish_list.txt: -------------------------------------------------------------------------------- 1 | Name label shopping_ingredients 2 | Chili for_sat_sun_mon schmand, 4x kidney bohnen, 1x passierte tomaten, wurzeln, mais, 2x gewürztüte 3 | Curry for_sat_sun_mon 2x gewürztüte, zuchini, 3x tomaten, 2x zwiebeln, wurzeln, paprika 4 | Tomatensuppe for_sat_sun_mon 8x tomaten, 1x gewürztüte, zwiebeln 5 | Kürbissuppe for_sat_sun_mon 1x kürbis, 1x sahne, 1x brühwürfel, 3x kartofflen 6 | Bolognese for_sat_sun_mon 4x tomaten, 2x tüte, 1x sahen, 1x spaghetti, 1x passierte tomaten, 1x reibekäse, wurzeln, 1x Hackfleisch 7 | Linsensuppe for_sat_sun_mon packung linsen, suppengemüse, 2x zwiebeln, 6x würstchen 8 | Nudelsalat for_sat_sun_mon 1x Pirelli Nudeln, 1x Salatdressing, Mais, 6x Würstchen, 2x Tomaten, 1x Gurken, 9 | Lasagne for_sat_sun_mon 1x Box Nudelplatten, 3x Paprika, 2x Zwiebeln, 2x Tomaten, 2x Gewürztüten, 1x Hackfleisch, 1x Creme Fraiche 10 | Auflauf for_sat_sun_mon 1x Sahne, 4x Paprika, 2x Zwiebeln, 2x Kochschinken, 8x Kartoffeln/ 1x Nudeln 11 | Stroganov + Vegetables for_sat_sun_mon 1x Pute, 1x Creme Fraiche, 1x saure sahne, 3x paprika, senf, 2x zwiebeln 12 | Cremesuppe for_sat_sun_mon 1x hack, 6x lauchstangen, 2x zwiebeln, 1x sahne schmelzkäse / frischkäse, 1x kräuter schmelzkäse / frischkäse 13 | Tuna always_frieday 1x tuna, 1x saure sahne, 1x spaghetti 14 | Wurstgulasch - 1x schlagsahne, 6x würstchen, 1x Eiernudeln 15 | Gnocchi - 1x Gnochi, 1x Frischkäse, 1x Spinat 16 | Tüte - 1x Tüte 17 | Frühlingsrollen - 1x Frühlingsrolle 18 | Pelmini - 1x Pelmini 19 | Cans - 2x cans 20 | Kartoffeln, Eier, Quark, Gemüse - 1x quark, 1x gemüse, 4x eier 21 | Chicken mit Quark - 1x chicken nuggets, 1x quark 22 | Würstchen mit Sauerkraut for_two_days 1x Sauerkraut, 8x Kartoffeln, 6x Würstchen 23 | Fisch - 1x sauhre sahne, 8x Kartoffeln, 1x Fisch, 1x Tafelmehrrettich 24 | Bratwurst Kartoffel Quark for_two_days 6x Bratwurst, 2x Quark, 8x Kartoffeln 25 | Sushi - 1x Sushi 26 | Schnitzel + Püree - 1x Schnitzel, 6x Kartoffeln 27 | Nudeln mit Gemüse und Chickenwurst - 1x Spaghetti, 1x Gemüse, 1x Chickenwurst 28 | Fischstäbchen - 1x Fischstäbchen, 1x Gurke 29 | Bami Gorgeng - 1x Bami Goreng -------------------------------------------------------------------------------- /meal_planner/last_week_schedule.txt: -------------------------------------------------------------------------------- 1 | KW Montag Dienstag Mittwoch Donnerstag Freitag Samstag Sonntag 2 | 33 Chili Tüte Wurstgulasch Gnocci Tuna Curry Curry -------------------------------------------------------------------------------- /meal_planner/main.py: -------------------------------------------------------------------------------- 1 | from crewai import Agent, Task, Crew, Process 2 | from crewai_tools import FileReadTool, DirectoryReadTool 3 | 4 | from langchain_openai import ChatOpenAI 5 | import agentops 6 | 7 | agentops.init(default_tags=["dish_schedule"]) 8 | 9 | from dotenv import load_dotenv 10 | load_dotenv() 11 | 12 | docs_tool = DirectoryReadTool(directory='videos/video_7') 13 | file_tool = FileReadTool() 14 | 15 | OpenAIGPT4 = ChatOpenAI( 16 | model="gpt-4o-2024-08-06" 17 | ) 18 | 19 | OpenAIGPT4MINI = ChatOpenAI( 20 | model="gpt-4o-mini" 21 | ) 22 | 23 | AGENT_MODEL = OpenAIGPT4MINI 24 | 25 | dish_scheduler = Agent( 26 | role="Weekly Dish Planner", 27 | goal="Generate a weekly dish schedule based on past cooking habits and user preferences.", 28 | backstory="""You are responsible for ensuring the user has a varied and satisfying meal 29 | plan each week, while also considering special requests.""", 30 | verbose=True, 31 | allow_delegation=False, 32 | memory=True, 33 | llm = AGENT_MODEL, 34 | ) 35 | 36 | file_reader = Agent( 37 | role="File Reader", 38 | goal="read data from files and pass it to the Weekly Dish Planner", 39 | backstory="""you are responsible to get all the data neeed by the Weekly Dish Planner""", 40 | verbose=True, 41 | memory=False, 42 | allow_delegation=True, 43 | tools=[docs_tool,file_tool ], 44 | llm = AGENT_MODEL, 45 | ) 46 | 47 | read_data = Task( 48 | description="""Read the dish list from dish_list.txt and last week schedule from 49 | last_week_schedule.txt and pass the data to the Weekly Dish Planner.""", 50 | expected_output="a string with the data from the files", 51 | agent=file_reader, 52 | ) 53 | 54 | generate_schedule_task = Task( 55 | description=( 56 | """Based on the provided dish list and last week's schedule, generate a new dish 57 | schedule for the next week (7 suggestions in total) that consider 58 | the users instruction: {user_instruction} 59 | Importand: respect the infomation of the labels 60 | Make sure to check with a human if the draft is good before finalizing your answer.""" 61 | ), 62 | expected_output="""" 63 | A tab seperated text containing the schedule for the next week, including the 64 | ingredients needed for each dish 65 | Example Output: 66 | Montag Dienstag Mittwoch Donnerstag Freitag Samstag Sonntag 67 | Bolognese Nudelsalat Kürbissuppe Frühlingsrollen Tuna Cremesuppe Lasagne 68 | 69 | Ingredients Needed: 70 | 71 | - Bolognese: 4x tomaten, 2x tüte, 1x sahne, 1x spaghetti, 1x passierte tomaten, 1x reibekäse, wurzeln, 1x Hackfleisch 72 | - Nudelsalat: 1x Pirelli Nudeln, 1x Salatdressing, Mais, 6x Würstchen, 2x Tomaten, 1x Gurken 73 | - Kürbissuppe: 1x kürbis, 1x sahne, 1x brühwürfel, 3x kartofflen 74 | - Frühlingsrollen: 1x Frühlingsrolle 75 | - Tuna: 1x tuna, 1x saure sahne, 1x spaghetti 76 | - Cremesuppe: 1x hack, 6x lauchstangen, 2x zwiebeln, 1x sahne schmelzkäse / frischkäse, 1x kräuter schmelzkäse / frischkäse 77 | - Lasagne: 1x Box Nudelplatten, 3x Paprika, 2x Zwiebeln, 2x Tomaten, 2x Gewürztüten, 1x Hackfleisch, 1x Creme Fraiche 78 | """, 79 | agent=dish_scheduler, 80 | human_input=True 81 | ) 82 | 83 | generate_shopping_list_task = Task( 84 | description="""If the user approves the schedule, generate a shopping list based on the 85 | ingredients needed for the new schedule, all the ingredients are provided in the dish list. 86 | dont invent new ingredients, only use the ingredients from the dish list. 87 | 88 | """, 89 | expected_output=""" 90 | a shopping list with the ingredients needed for the new schedule. 91 | Example output: 92 | 1x Hack 93 | 6x Lauchstangen 94 | 2x Zwiebeln 95 | 1x Sahne Schmelzkäse / Frischkäse 96 | 1x Kräuter Schmelzkäse / Frischkäse 97 | 1x Tuna 98 | 1x Saure Sahne 99 | 1x Spaghetti 100 | 1x Schlagsahne 101 | 6x Würstchen 102 | 1x Eiernudeln 103 | """, 104 | agent=dish_scheduler, 105 | ) 106 | 107 | 108 | inputs = { 109 | "user_instruction": """Create a new dish schedule for the next week, include one special 110 | meal that I did not cook yet""" 111 | } 112 | 113 | crew = Crew( 114 | agents=[dish_scheduler], 115 | tasks=[read_data, generate_schedule_task, generate_shopping_list_task], 116 | process=Process.sequential 117 | ) 118 | 119 | result = crew.kickoff(inputs=inputs) 120 | 121 | print("######################") 122 | print(result) 123 | print("Crew usage", crew.usage_metrics) 124 | agentops.end_session("Success") -------------------------------------------------------------------------------- /readmes/claude-mcp.md: -------------------------------------------------------------------------------- 1 | # Claude Desktop Settings Configuration 2 | 3 | https://www.anthropic.com/news/model-context-protocol 4 | 5 | https://github.com/modelcontextprotocol/servers/tree/main 6 | 7 | 8 | This guide explains how to configure settings for the Claude desktop application. 9 | 10 | ## Configuration Location 11 | 12 | The Claude desktop app stores its configuration in the following location: 13 | 14 | ```bash 15 | ~/Library/Application Support/Claude/ 16 | ``` 17 | 18 | ## Setting Up Configuration 19 | 20 | 1. **Create the Claude configuration directory if it doesn't exist:** 21 | 22 | ```bash 23 | open ~/Library/Application\ Support/Claude 24 | ``` 25 | 26 | 2. **Create the configuration file:** 27 | 28 | ```bash 29 | touch ~/Library/Application\ Support/Claude/claude_desktop_config.json 30 | ``` 31 | 32 | ## Configuration Options 33 | 34 | The `claude_desktop_config.json` file allows you to customize various settings for the Claude desktop application. Add your desired configuration options in JSON format. 35 | 36 | **GitHub integration configuration:** 37 | 38 | https://github.com/modelcontextprotocol/servers/tree/main/src/github 39 | 40 | ```json 41 | { 42 | "github": { 43 | "command": "npx", 44 | "args": [ 45 | "-y", 46 | "@modelcontextprotocol/server-github" 47 | ], 48 | "env": { 49 | "GITHUB_PERSONAL_ACCESS_TOKEN": "access-token" 50 | } 51 | } 52 | } 53 | ``` 54 | 55 | 56 | 57 | **Brave Search integration configuration:** 58 | 59 | https://github.com/modelcontextprotocol/servers/tree/main/src/brave-search 60 | 61 | 62 | ```json 63 | { 64 | "brave-search": { 65 | "command": "npx", 66 | "args": [ 67 | "-y", 68 | "@modelcontextprotocol/server-brave-search" 69 | ], 70 | "env": { 71 | "BRAVE_API_KEY": "api-key" 72 | } 73 | } 74 | } 75 | ``` 76 | 77 | ## Notes 78 | 79 | - **Important:** Ensure that `npx` is installed globally and not managed via `nvm`. This is crucial for the integrations to function correctly. 80 | - Make sure to use valid JSON syntax in the configuration file. 81 | - Restart the Claude desktop application after making changes to apply new settings. 82 | - Back up your configuration file before making significant changes. 83 | 84 | ## Example Configuration 85 | 86 | **Available GitHub operations:** 87 | 88 | - `create_or_update_file`: Create/update single file 89 | - `search_repositories`: Search repos 90 | - `create_repository`: Create new repo 91 | - `get_file_contents`: Get file/directory contents 92 | - `push_files`: Push multiple files in one commit 93 | - `create_issue`: Create new issue 94 | - `create_pull_request`: Create new PR 95 | - `fork_repository`: Fork a repo 96 | - `create_branch`: Create new branch 97 | 98 | ### GitHub Operations 99 | 100 | #### Fork Repository 101 | Creates a copy of a repository in your account or specified organization. 102 | ```json 103 | { 104 | "owner": "original-owner", 105 | "repo": "repository-name", 106 | "organization": "target-org" // Optional 107 | } 108 | ``` 109 | 110 | #### Create Branch 111 | Creates a new branch from the default or specified source branch. 112 | ```json 113 | { 114 | "owner": "repository-owner", 115 | "repo": "repository-name", 116 | "branch": "new-branch-name", 117 | "from_branch": "main" // Optional, defaults to default branch 118 | } 119 | ``` 120 | 121 | #### Search Repositories 122 | Searches GitHub repositories using the provided query. 123 | ```json 124 | { 125 | "query": "search query string", 126 | "page": 1, // Optional 127 | "perPage": 30 // Optional 128 | } 129 | ``` 130 | 131 | #### Create Repository 132 | Creates a new repository in your account. 133 | ```json 134 | { 135 | "name": "new-repository", 136 | "private": true, 137 | "description": "Repository description" // Optional 138 | } 139 | ``` 140 | 141 | #### Get File Contents 142 | Retrieves contents of a file or directory. 143 | ```json 144 | { 145 | "owner": "repository-owner", 146 | "repo": "repository-name", 147 | "path": "path/to/file", 148 | "branch": "main" // Optional 149 | } 150 | ``` 151 | 152 | #### Create or Update File 153 | Creates or updates a single file. 154 | ```json 155 | { 156 | "owner": "repository-owner", 157 | "repo": "repository-name", 158 | "path": "path/to/file", 159 | "content": "file content", 160 | "message": "commit message", 161 | "branch": "target-branch", 162 | "sha": "existing-file-sha" // Optional, required for updates 163 | } 164 | ``` 165 | 166 | #### Push Files 167 | Pushes multiple files in a single commit. 168 | ```json 169 | { 170 | "owner": "repository-owner", 171 | "repo": "repository-name", 172 | "branch": "target-branch", 173 | "message": "commit message", 174 | "files": [ 175 | { 176 | "path": "path/to/file1", 177 | "content": "file content" 178 | }, 179 | { 180 | "path": "path/to/file2", 181 | "content": "file content" 182 | } 183 | ] 184 | } 185 | ``` 186 | 187 | #### Create Issue 188 | Creates a new issue. 189 | ```json 190 | { 191 | "owner": "repository-owner", 192 | "repo": "repository-name", 193 | "title": "Issue title", 194 | "body": "Issue description", 195 | "labels": ["bug", "help wanted"] // Optional 196 | } 197 | ``` 198 | 199 | #### Create Pull Request 200 | Creates a new pull request. 201 | ```json 202 | { 203 | "owner": "repository-owner", 204 | "repo": "repository-name", 205 | "title": "Pull request title", 206 | "head": "source-branch", 207 | "base": "target-branch", 208 | "body": "Pull request description" // Optional 209 | } 210 | ``` 211 | 212 | -------------------------------------------------------------------------------- /sell_ai_agents/cost_reduction.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Florenz23/ai-agent-videos/4d06a1d2956ea7f16b8e11074e71f5c16e91f41d/sell_ai_agents/cost_reduction.pptx -------------------------------------------------------------------------------- /structured_data/autogen/autogen_structured_output.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | import json 4 | import time 5 | import sys 6 | import asyncio 7 | from typing import Dict, Any, List, Optional 8 | from uuid import uuid4 9 | from dotenv import load_dotenv 10 | from pydantic import BaseModel, Field 11 | 12 | # Add project root to Python path 13 | project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../../..")) 14 | sys.path.insert(0, project_root) 15 | 16 | # AutoGen imports 17 | from autogen_agentchat.agents import AssistantAgent 18 | from autogen_agentchat.messages import TextMessage 19 | from autogen_core import CancellationToken 20 | from autogen_ext.models.openai import OpenAIChatCompletionClient 21 | from autogen_core.tools import FunctionTool 22 | 23 | # Import Yahoo Finance tool 24 | from src.tools.tool_yahoo_finance import get_stock_data 25 | 26 | # Load environment variables 27 | load_dotenv() 28 | 29 | # Read Warren Buffett investment principles 30 | with open('src/workflows/structured_data/warren_buffet_investement_principles.txt', 'r') as file: 31 | warren_buffett_principles = file.read() 32 | 33 | # Define the tool function 34 | async def analyze_stock_async(ticker: str) -> str: 35 | """ 36 | Retrieves financial data for a stock using Yahoo Finance API 37 | """ 38 | print(f"Using tool to retrieve stock data for: {ticker}") 39 | stock_data = get_stock_data(ticker) 40 | print(f"Stock data retrieved for {ticker}") 41 | return "\n".join(stock_data) 42 | 43 | # Pydantic models for structured output 44 | class RelevantKPI(BaseModel): 45 | key: str = Field(description="Name of the KPI") 46 | rating: int = Field(description="Rating from 0-10, where 10 is best") 47 | 48 | class InvestmentAnalysis(BaseModel): 49 | reasoning: str = Field(description="Detailed reasoning for the investment decision based on Warren Buffett's principles") 50 | rating: int = Field(description="Overall investment rating from 0-10, where 10 is best") 51 | relevant_kpis: List[RelevantKPI] = Field(description="List of relevant KPIs with individual ratings") 52 | improvement_requirements: str = Field(description="Areas where the company needs to improve") 53 | 54 | class AutogenStructuredOutput: 55 | def __init__(self, input_data: Dict[str, Any]): 56 | """ 57 | Initialize the AutogenStructuredOutput for a stock analysis. 58 | 59 | Args: 60 | input_data: Dictionary containing workflow configuration and input data 61 | """ 62 | self.input_data = input_data 63 | self.ticker = input_data["workflow_input_data"]["ticker"] 64 | self.record_id = uuid4() 65 | 66 | self.model = input_data["model"] 67 | 68 | # Create the stock analysis tool 69 | self.analyze_stock_tool = FunctionTool( 70 | analyze_stock_async, 71 | description="Retrieve financial data for a stock using Yahoo Finance API", 72 | strict=True 73 | ) 74 | 75 | async def run(self) -> Dict[str, Any]: 76 | """ 77 | Run the stock analysis based on Warren Buffett's principles. 78 | 79 | Returns: 80 | Dictionary with the analysis results 81 | """ 82 | print(f"\nAnalyzing stock: {self.ticker}...") 83 | 84 | # Create an OpenAI model client with structured output 85 | model_client = OpenAIChatCompletionClient( 86 | model=self.model, 87 | response_format=InvestmentAnalysis, 88 | ) 89 | 90 | # Create a single agent that handles both analysis and structured output 91 | analyst = AssistantAgent( 92 | name="investment_analyst", 93 | description="An investment analyst who follows Warren Buffett's principles", 94 | model_client=model_client, 95 | system_message=f"""You are an expert investment analyst who follows Warren Buffett's 96 | investment principles to evaluate stocks. You believe in value investing and 97 | long-term perspectives. 98 | 99 | Here are Warren Buffett's investment principles: 100 | {warren_buffett_principles} 101 | 102 | Your task is to analyze the stock with ticker {self.ticker} based on Warren Buffett's investment principles. 103 | Use the analyze_stock tool to retrieve the financial data for this stock. 104 | 105 | After analyzing the stock, provide a structured investment analysis that includes: 106 | 1. Detailed reasoning for your investment decision based on Warren Buffett's principles 107 | 2. Overall investment rating from 0-10, where 10 is best 108 | 3. List of relevant KPIs with individual ratings from 0-10 109 | 4. Areas where the company needs to improve 110 | 111 | Format your response following the InvestmentAnalysis schema strictly. 112 | """, 113 | tools=[self.analyze_stock_tool], 114 | reflect_on_tool_use=True, 115 | ) 116 | 117 | # Create a message to send to the agent 118 | message = TextMessage( 119 | content=f"Analyze {self.ticker} stock and provide a structured investment analysis based on Warren Buffett's principles.", 120 | source="user" 121 | ) 122 | 123 | # Send the message to the agent and get the response 124 | response = await analyst.on_messages( 125 | [message], 126 | cancellation_token=CancellationToken(), 127 | ) 128 | 129 | # Get the message content 130 | final_content = response.chat_message.content 131 | 132 | try: 133 | # Parse the content as JSON directly 134 | analysis_dict = json.loads(final_content) 135 | print(f"\nStructured Output Demonstration:") 136 | print(f"✅ Successfully received structured JSON output for {self.ticker}") 137 | 138 | # Print structure validation to show it's properly structured 139 | print(f"🔍 Output contains expected fields:") 140 | print(f" • reasoning: {'✓' if 'reasoning' in analysis_dict else '✗'}") 141 | print(f" • rating: {'✓' if 'rating' in analysis_dict else '✗'}") 142 | print(f" • relevant_kpis: {'✓' if 'relevant_kpis' in analysis_dict else '✗'}") 143 | print(f" • improvement_requirements: {'✓' if 'improvement_requirements' in analysis_dict else '✗'}") 144 | 145 | return analysis_dict 146 | except Exception as e: 147 | # If direct parsing fails, try to extract JSON from the message 148 | print(f"Failed to parse structured output directly: {e}") 149 | try: 150 | # Try to extract JSON from text if it's embedded 151 | json_match = re.search(r'```json\s*(.*?)\s*```', final_content, re.DOTALL) 152 | if json_match: 153 | json_str = json_match.group(1) 154 | parsed_data = json.loads(json_str) 155 | print(f"Successfully extracted and analyzed JSON for {self.ticker}") 156 | return parsed_data 157 | except Exception as json_error: 158 | print(f"Failed to extract JSON: {json_error}") 159 | 160 | # Fallback if no valid response 161 | print(f"Failed to get structured analysis for {self.ticker}") 162 | return { 163 | "reasoning": "Analysis failed", 164 | "rating": 0, 165 | "relevant_kpis": [], 166 | "improvement_requirements": "Unable to complete analysis" 167 | } 168 | 169 | def sync_run(self) -> Dict[str, Any]: 170 | """ 171 | Synchronous wrapper for the run method. 172 | """ 173 | return asyncio.run(self.run()) 174 | 175 | if __name__ == "__main__": 176 | # Define input data 177 | new_input_data = { 178 | "workflow": "structured_data", 179 | "model": "gpt-4o-mini", 180 | "framework": "autogen", 181 | "llm_provider": "openai", 182 | "workflow_input_data": { 183 | "ticker": "AAPL" 184 | } 185 | } 186 | 187 | # Create and run the stock analyzer 188 | start_time = time.time() 189 | analyzer = AutogenStructuredOutput(input_data=new_input_data) 190 | result = analyzer.sync_run() 191 | 192 | # Print JSON version 193 | result_json = json.dumps(result, indent=4) 194 | print(f"\nJSON Result:\n{result_json}") 195 | 196 | # Print human-readable version 197 | print("\n" + "="*50) 198 | print(f"INVESTMENT ANALYSIS FOR {new_input_data['workflow_input_data']['ticker']}") 199 | print("="*50) 200 | 201 | print("\n📝 REASONING:") 202 | print(result['reasoning']) 203 | 204 | print(f"\n⭐ OVERALL RATING: {result['rating']}/10") 205 | 206 | print("\n📊 RELEVANT KPIs:") 207 | for kpi in result['relevant_kpis']: 208 | print(f" • {kpi['key']}: {kpi['rating']}/10") 209 | 210 | print("\n🔍 IMPROVEMENT REQUIREMENTS:") 211 | print(result['improvement_requirements']) 212 | 213 | print("\n" + "="*50) 214 | 215 | end_time = time.time() 216 | print(f"Time taken: {end_time - start_time:.2f} seconds") 217 | -------------------------------------------------------------------------------- /structured_data/crewai/crewai_structured_output.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | from crewai import Agent, Task, Crew, Process, LLM 4 | from crewai.tools import tool 5 | import asyncio 6 | from dotenv import load_dotenv 7 | import json 8 | import time 9 | from pydantic import BaseModel 10 | from typing import Dict, Any, List, Optional 11 | from uuid import uuid4 12 | load_dotenv() 13 | 14 | # Import Yahoo Finance tool 15 | from src.tools.tool_yahoo_finance import get_stock_data 16 | 17 | # Read Warren Buffett investment principles 18 | with open('src/workflows/structured_data/warren_buffet_investement_principles.txt', 'r') as file: 19 | warren_buffett_principles = file.read() 20 | 21 | @tool 22 | def analyze_stock(ticker: str) -> str: 23 | """ 24 | Retrieves financial data for a stock using Yahoo Finance API 25 | """ 26 | print(f"Using tool to retrieve stock data for: {ticker}") 27 | stock_data = get_stock_data(ticker) 28 | print(f"Stock data retrieved for {ticker}") 29 | return "\n".join(stock_data) 30 | 31 | # Pydantic models to parse the JSON returned by each task 32 | class RelevantKPI(BaseModel): 33 | key: str 34 | rating: int 35 | 36 | class InvestmentAnalysis(BaseModel): 37 | reasoning: str 38 | rating: int # 0-10, 10 is best 39 | relevant_kpis: List[RelevantKPI] 40 | improvement_requirements: str 41 | 42 | class CrewAiStructuredOutput: 43 | def __init__(self, input_data: Dict[str, Any]): 44 | """ 45 | Initialize the CrewAiStructuredData for a stock analysis. 46 | 47 | Args: 48 | input_data: Dictionary containing workflow configuration and input data 49 | """ 50 | self.input_data = input_data 51 | self.ticker = input_data["workflow_input_data"]["ticker"] 52 | self.record_id = uuid4() 53 | 54 | # Initialize LLM 55 | self.llm = LLM( 56 | model=input_data["model"] 57 | ) 58 | 59 | def run(self) -> Dict[str, Any]: 60 | """ 61 | Run the stock analysis based on Warren Buffett's principles. 62 | 63 | Returns: 64 | Dictionary with the analysis results 65 | """ 66 | print(f"\nAnalyzing stock: {self.ticker}...") 67 | 68 | # Create the stock analyst agent 69 | stock_analyst = Agent( 70 | role='Investment Analyst', 71 | goal='Analyze stocks using Warren Buffett\'s investment principles', 72 | backstory=f"""You are an expert investment analyst who follows Warren Buffett's 73 | investment principles to evaluate stocks. You believe in value investing and 74 | long-term perspectives. 75 | 76 | Here are Warren Buffett's investment principles: 77 | {warren_buffett_principles}""", 78 | allow_delegation=False, 79 | tools=[analyze_stock], 80 | llm=self.llm 81 | ) 82 | 83 | # Create the analysis task 84 | stock_analysis_task = Task( 85 | description=f""" 86 | Analyze the stock with ticker {self.ticker} based on Warren Buffett's investment principles. 87 | Retrieve the financial data using the analyze_stock tool then return clearly structured JSON 88 | response. Rating is between 0 and 10, where 10 is best. 89 | """, 90 | expected_output="A well-structured investment analysis in JSON format", 91 | agent=stock_analyst, 92 | output_json=InvestmentAnalysis 93 | ) 94 | 95 | # Create and run the crew 96 | crew = Crew( 97 | agents=[stock_analyst], 98 | tasks=[stock_analysis_task], 99 | verbose=False, 100 | process=Process.sequential 101 | ) 102 | 103 | # Kick off the crew and get the result 104 | crew_result = crew.kickoff() 105 | 106 | print(f"Successfully analyzed {self.ticker}") 107 | 108 | return crew_result 109 | 110 | if __name__ == "__main__": 111 | # Define input data 112 | new_input_data = { 113 | "workflow": "structured_data", 114 | "model": "gpt-4o-mini", 115 | "framework": "crewai", 116 | "llm_provider": "openai", 117 | "workflow_input_data": { 118 | "ticker": "AAPL" 119 | } 120 | } 121 | 122 | # Create and run the stock analyzer 123 | start_time = time.time() 124 | analyzer = CrewAiStructuredOutput(input_data=new_input_data) 125 | result = analyzer.run() 126 | 127 | # Get the result data and ensure it's properly parsed 128 | if isinstance(result.json, str): 129 | data = json.loads(result.json) 130 | else: 131 | data = result.json 132 | 133 | # Print JSON version 134 | result_json = json.dumps(data, indent=4) 135 | print(f"\nJSON Result:\n{result_json}") 136 | 137 | # Print human-readable version 138 | print("\n" + "="*50) 139 | print(f"INVESTMENT ANALYSIS FOR {new_input_data['workflow_input_data']['ticker']}") 140 | print("="*50) 141 | 142 | print("\n📝 REASONING:") 143 | print(data['reasoning']) 144 | 145 | print(f"\n⭐ OVERALL RATING: {data['rating']}/10") 146 | 147 | print("\n📊 RELEVANT KPIs:") 148 | for kpi in data['relevant_kpis']: 149 | print(f" • {kpi['key']}: {kpi['rating']}/10") 150 | 151 | print("\n🔍 IMPROVEMENT REQUIREMENTS:") 152 | print(data['improvement_requirements']) 153 | 154 | print("\n" + "="*50) 155 | 156 | end_time = time.time() 157 | print(f"Time taken: {end_time - start_time:.2f} seconds") 158 | -------------------------------------------------------------------------------- /structured_data/langchain/langchain_structured_output.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | import json 4 | import time 5 | import sys 6 | from typing import Dict, Any, List, Optional 7 | from uuid import uuid4 8 | from dotenv import load_dotenv 9 | from pydantic import BaseModel, Field 10 | 11 | # Add project root to Python path 12 | project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../../..")) 13 | sys.path.insert(0, project_root) 14 | 15 | # LangChain imports 16 | from langchain_openai import ChatOpenAI 17 | from langchain_core.tools import tool 18 | from langchain_core.messages import HumanMessage, ToolMessage 19 | from langchain_core.prompts import ChatPromptTemplate 20 | 21 | # Import Yahoo Finance tool 22 | from src.tools.tool_yahoo_finance import get_stock_data 23 | 24 | # Load environment variables 25 | load_dotenv() 26 | 27 | # Read Warren Buffett investment principles 28 | with open('src/workflows/structured_data/warren_buffet_investement_principles.txt', 'r') as file: 29 | warren_buffett_principles = file.read() 30 | 31 | @tool 32 | def analyze_stock(ticker: str) -> str: 33 | """ 34 | Retrieves financial data for a stock using Yahoo Finance API 35 | """ 36 | print(f"Using tool to retrieve stock data for: {ticker}") 37 | stock_data = get_stock_data(ticker) 38 | print(f"Stock data retrieved for {ticker}") 39 | return "\n".join(stock_data) 40 | 41 | # Pydantic models to parse the JSON returned by each task 42 | class RelevantKPI(BaseModel): 43 | key: str = Field(description="Name of the KPI") 44 | rating: int = Field(description="Rating from 0-10, where 10 is best") 45 | 46 | class InvestmentAnalysis(BaseModel): 47 | reasoning: str = Field(description="Detailed reasoning for the investment decision based on Warren Buffett's principles") 48 | rating: int = Field(description="Overall investment rating from 0-10, where 10 is best") 49 | relevant_kpis: List[RelevantKPI] = Field(description="List of relevant KPIs with individual ratings") 50 | improvement_requirements: str = Field(description="Areas where the company needs to improve") 51 | 52 | class LangchainStructuredOutput: 53 | def __init__(self, input_data: Dict[str, Any]): 54 | """ 55 | Initialize the LangchainStructuredOutput for a stock analysis. 56 | 57 | Args: 58 | input_data: Dictionary containing workflow configuration and input data 59 | """ 60 | self.input_data = input_data 61 | self.ticker = input_data["workflow_input_data"]["ticker"] 62 | self.record_id = uuid4() 63 | 64 | # Initialize LLM 65 | self.llm = ChatOpenAI( 66 | model=input_data["model"] 67 | ) 68 | 69 | # Set up tools 70 | self.tools = [analyze_stock] 71 | self.llm_with_tools = self.llm.bind_tools(self.tools) 72 | 73 | def run(self) -> Dict[str, Any]: 74 | """ 75 | Run the stock analysis based on Warren Buffett's principles. 76 | 77 | Returns: 78 | Dictionary with the analysis results 79 | """ 80 | print(f"\nAnalyzing stock: {self.ticker}...") 81 | 82 | # Create the prompt 83 | template = f"""You are an expert investment analyst who follows Warren Buffett's 84 | investment principles to evaluate stocks. You believe in value investing and 85 | long-term perspectives. 86 | 87 | Here are Warren Buffett's investment principles: 88 | {warren_buffett_principles} 89 | 90 | Please analyze the stock with ticker {{ticker}} based on Warren Buffett's investment principles. 91 | Use the analyze_stock tool to retrieve the financial data for this stock. 92 | """ 93 | 94 | prompt = ChatPromptTemplate.from_template(template) 95 | 96 | # Create initial message 97 | messages = [HumanMessage(content=prompt.format(ticker=self.ticker))] 98 | 99 | # First invocation: Model decides which tools to call 100 | ai_msg = self.llm_with_tools.invoke(messages) 101 | messages.append(ai_msg) 102 | 103 | # Process tool calls and collect results 104 | tool_outputs = [] 105 | if ai_msg.tool_calls: 106 | for tool_call in ai_msg.tool_calls: 107 | if tool_call["name"].lower() == "analyze_stock": 108 | tool_output = analyze_stock.invoke(tool_call["args"]["ticker"]) 109 | tool_outputs.append( 110 | ToolMessage(content=str(tool_output), tool_call_id=tool_call["id"]) 111 | ) 112 | 113 | # Append tool results to message history 114 | messages.extend(tool_outputs) 115 | 116 | # Add a final prompt to produce structured output 117 | final_prompt = """ 118 | Based on the stock data and Warren Buffett's principles, please provide a structured 119 | investment analysis then return clearly structured JSON response. 120 | Rating is between 0 and 10, where 10 is best. 121 | """ 122 | 123 | messages.append(HumanMessage(content=final_prompt)) 124 | 125 | # Use structured output for final analysis 126 | structured_llm = self.llm.with_structured_output(InvestmentAnalysis) 127 | final_response = structured_llm.invoke(messages) 128 | 129 | print(f"Successfully analyzed {self.ticker}") 130 | 131 | # Convert to dictionary for consistency with CrewAI output 132 | return final_response.dict() 133 | 134 | if __name__ == "__main__": 135 | # Define input data 136 | new_input_data = { 137 | "workflow": "structured_data", 138 | "model": "gpt-4o-mini", 139 | "framework": "langchain", 140 | "llm_provider": "openai", 141 | "workflow_input_data": { 142 | "ticker": "AAPL" 143 | } 144 | } 145 | 146 | # Create and run the stock analyzer 147 | start_time = time.time() 148 | analyzer = LangchainStructuredOutput(input_data=new_input_data) 149 | result = analyzer.run() 150 | 151 | # Print JSON version 152 | result_json = json.dumps(result, indent=4) 153 | print(f"\nJSON Result:\n{result_json}") 154 | 155 | # Print human-readable version 156 | print("\n" + "="*50) 157 | print(f"INVESTMENT ANALYSIS FOR {new_input_data['workflow_input_data']['ticker']}") 158 | print("="*50) 159 | 160 | print("\n📝 REASONING:") 161 | print(result['reasoning']) 162 | 163 | print(f"\n⭐ OVERALL RATING: {result['rating']}/10") 164 | 165 | print("\n📊 RELEVANT KPIs:") 166 | for kpi in result['relevant_kpis']: 167 | print(f" • {kpi['key']}: {kpi['rating']}/10") 168 | 169 | print("\n🔍 IMPROVEMENT REQUIREMENTS:") 170 | print(result['improvement_requirements']) 171 | 172 | print("\n" + "="*50) 173 | 174 | end_time = time.time() 175 | print(f"Time taken: {end_time - start_time:.2f} seconds") 176 | -------------------------------------------------------------------------------- /structured_data/openai_agents/openai_agents_structred_output.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | import json 4 | import time 5 | import sys 6 | from typing import Dict, Any, List, Optional 7 | from uuid import uuid4 8 | from dotenv import load_dotenv 9 | from pydantic import BaseModel, Field 10 | 11 | # Add project root to Python path 12 | project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../../..")) 13 | sys.path.insert(0, project_root) 14 | 15 | # OpenAI Agents imports 16 | import asyncio 17 | from agents import Agent, Runner, function_tool 18 | 19 | # Import Yahoo Finance tool 20 | from src.tools.tool_yahoo_finance import get_stock_data 21 | 22 | # Load environment variables 23 | load_dotenv() 24 | 25 | # Read Warren Buffett investment principles 26 | with open('src/workflows/structured_output/warren_buffet_investement_principles.txt', 'r') as file: 27 | warren_buffett_principles = file.read() 28 | 29 | # Pydantic models to parse the structured output 30 | class RelevantKPI(BaseModel): 31 | key: str = Field(description="Name of the KPI") 32 | rating: int = Field(description="Rating from 0-10, where 10 is best") 33 | 34 | class InvestmentAnalysis(BaseModel): 35 | reasoning: str = Field(description="Detailed reasoning for the investment decision based on Warren Buffett's principles") 36 | rating: int = Field(description="Overall investment rating from 0-10, where 10 is best") 37 | relevant_kpis: List[RelevantKPI] = Field(description="List of relevant KPIs with individual ratings") 38 | improvement_requirements: str = Field(description="Areas where the company needs to improve") 39 | 40 | class OpenaiAgentsStructuredOutput: 41 | def __init__(self, input_data: Dict[str, Any]): 42 | """ 43 | Initialize the OpenaiAgentsStructuredOutput for a stock analysis. 44 | 45 | Args: 46 | input_data: Dictionary containing workflow configuration and input data 47 | """ 48 | self.input_data = input_data 49 | self.ticker = input_data["workflow_input_data"]["ticker"] 50 | self.record_id = uuid4() 51 | 52 | # Create the analyze_stock tool function 53 | @function_tool 54 | def analyze_stock(ticker: str) -> str: 55 | """ 56 | Retrieves financial data for a stock using Yahoo Finance API 57 | 58 | Args: 59 | ticker: The stock ticker symbol (e.g. 'AAPL') 60 | 61 | Returns: 62 | A string containing key financial metrics for the stock 63 | """ 64 | print(f"Using tool to retrieve stock data for: {ticker}") 65 | stock_data = get_stock_data(ticker) 66 | print(f"Stock data retrieved for {ticker}") 67 | return "\n".join(stock_data) 68 | 69 | # Set up the agent with the instructions and tools 70 | self.stock_analyzer = Agent( 71 | name="Investment Analyst", 72 | instructions=f"""You are an expert investment analyst who follows Warren Buffett's 73 | investment principles to evaluate stocks. You believe in value investing and 74 | long-term perspectives. 75 | 76 | Here are Warren Buffett's investment principles: 77 | {warren_buffett_principles} 78 | 79 | Analyze the stock ticker provided by the user based on Warren Buffett's principles. 80 | Use the analyze_stock tool to retrieve financial data for the stock. 81 | Your final response should be a structured JSON object following the InvestmentAnalysis schema. 82 | """, 83 | tools=[analyze_stock], 84 | output_type=InvestmentAnalysis, 85 | ) 86 | 87 | async def run(self) -> Dict[str, Any]: 88 | """ 89 | Run the stock analysis based on Warren Buffett's principles. 90 | 91 | Returns: 92 | The full result object containing token usage and structured output 93 | """ 94 | print(f"\nAnalyzing stock: {self.ticker}...") 95 | 96 | # Run the agent with a prompt 97 | prompt = f"Please analyze the stock with ticker {self.ticker} based on Warren Buffett's investment principles. Retrieve the stock data using the analyze_stock tool." 98 | 99 | result = await Runner.run(self.stock_analyzer, input=prompt) 100 | 101 | print(f"Successfully analyzed {self.ticker}") 102 | 103 | # Return the full result object to capture token usage information 104 | return result 105 | 106 | if __name__ == "__main__": 107 | # Define input data 108 | new_input_data = { 109 | "workflow": "structured_output", 110 | "model": "gpt-4.1-nano", 111 | # "model": "gpt-4.1-mini", 112 | "framework": "openai_agents", 113 | "llm_provider": "openai", 114 | "workflow_input_data": { 115 | "ticker": "AAPL" 116 | } 117 | } 118 | 119 | # Create and run the stock analyzer 120 | start_time = time.time() 121 | 122 | analyzer = OpenaiAgentsStructuredOutput(input_data=new_input_data) 123 | result = asyncio.run(analyzer.run()) 124 | 125 | # Print JSON version 126 | result_json = result.final_output.model_dump() 127 | print(f"\nJSON Result:\n{result_json}") 128 | 129 | # Print human-readable version 130 | print("\n" + "="*50) 131 | print(f"INVESTMENT ANALYSIS FOR {new_input_data['workflow_input_data']['ticker']}") 132 | print("="*50) 133 | 134 | print("\n📝 REASONING:") 135 | print(result.final_output.reasoning) 136 | 137 | print(f"\n⭐ OVERALL RATING: {result.final_output.rating}/10") 138 | 139 | print("\n📊 RELEVANT KPIs:") 140 | for kpi in result.final_output.relevant_kpis: 141 | print(f" • {kpi.key}: {kpi.rating}/10") 142 | 143 | print("\n🔍 IMPROVEMENT REQUIREMENTS:") 144 | print(result.final_output.improvement_requirements) 145 | 146 | print("\n" + "="*50) 147 | 148 | end_time = time.time() 149 | print(f"Time taken: {end_time - start_time:.2f} seconds") 150 | -------------------------------------------------------------------------------- /structured_data/pydantic_agents/pydantic_structured_output.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | import json 4 | import time 5 | import sys 6 | from typing import Dict, Any, List, Optional 7 | from uuid import uuid4 8 | from dotenv import load_dotenv 9 | from pydantic import BaseModel, Field 10 | 11 | # Add project root to Python path 12 | project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../../..")) 13 | sys.path.insert(0, project_root) 14 | 15 | # Pydantic AI imports 16 | from pydantic_ai import Agent, RunContext 17 | 18 | # Import Yahoo Finance tool 19 | from src.tools.tool_yahoo_finance import get_stock_data 20 | 21 | # Load environment variables 22 | load_dotenv() 23 | 24 | # Read Warren Buffett investment principles 25 | with open('src/workflows/structured_output/warren_buffet_investement_principles.txt', 'r') as file: 26 | warren_buffett_principles = file.read() 27 | 28 | # Pydantic models to parse the structured output 29 | class RelevantKPI(BaseModel): 30 | key: str = Field(description="Name of the KPI") 31 | rating: int = Field(description="Rating from 0-10, where 10 is best") 32 | 33 | class InvestmentAnalysis(BaseModel): 34 | reasoning: str = Field(description="Detailed reasoning for the investment decision based on Warren Buffett's principles") 35 | rating: int = Field(description="Overall investment rating from 0-10, where 10 is best") 36 | relevant_kpis: List[RelevantKPI] = Field(description="List of relevant KPIs with individual ratings") 37 | improvement_requirements: str = Field(description="Areas where the company needs to improve") 38 | 39 | class StockAnalyzerDependencies: 40 | """Dependencies for the stock analyzer agent""" 41 | def __init__(self, ticker: str): 42 | self.ticker = ticker 43 | 44 | class PydanticStructuredOutput: 45 | def __init__(self, input_data: Dict[str, Any]): 46 | """ 47 | Initialize the PydanticStructuredOutput for a stock analysis. 48 | 49 | Args: 50 | input_data: Dictionary containing workflow configuration and input data 51 | """ 52 | self.input_data = input_data 53 | 54 | # Make sure workflow_input_data exists and has expected structure 55 | if not input_data.get("workflow_input_data"): 56 | raise ValueError("Missing workflow_input_data in input") 57 | 58 | # Get ticker from input data with fallback to AAPL 59 | self.ticker = input_data.get("workflow_input_data", {}).get("ticker", "AAPL") 60 | self.record_id = uuid4() 61 | 62 | # Get LLM provider or default to 'openai' 63 | llm_provider = input_data.get("llm_provider", "openai") 64 | model = input_data.get("model", "gpt-4o-mini") 65 | 66 | # Initialize the Pydantic AI agent 67 | self.stock_analyzer = Agent( 68 | f"{llm_provider}:{model}", 69 | deps_type=StockAnalyzerDependencies, 70 | output_type=InvestmentAnalysis, 71 | system_prompt=f"""You are an expert investment analyst who follows Warren Buffett's 72 | investment principles to evaluate stocks. You believe in value investing and 73 | long-term perspectives. 74 | 75 | Here are Warren Buffett's investment principles: 76 | {warren_buffett_principles} 77 | """ 78 | ) 79 | 80 | # Register tools 81 | @self.stock_analyzer.tool 82 | async def analyze_stock(ctx: RunContext[StockAnalyzerDependencies]) -> str: 83 | """ 84 | Retrieves financial data for a stock using Yahoo Finance API 85 | """ 86 | print(f"Using tool to retrieve stock data for: {ctx.deps.ticker}") 87 | stock_data = get_stock_data(ctx.deps.ticker) 88 | print(f"Stock data retrieved for {ctx.deps.ticker}") 89 | return "\n".join(stock_data) 90 | 91 | async def run(self) -> Dict[str, Any]: 92 | """ 93 | Run the stock analysis based on Warren Buffett's principles. 94 | 95 | Returns: 96 | Dictionary with the analysis results 97 | """ 98 | try: 99 | print(f"\nAnalyzing stock: {self.ticker}...") 100 | 101 | # Create dependencies 102 | deps = StockAnalyzerDependencies(ticker=self.ticker) 103 | 104 | # Run the agent 105 | prompt = f"Please analyze the stock with ticker {self.ticker} based on Warren Buffett's investment principles. Use the analyze_stock tool to retrieve the financial data, then provide a structured investment analysis." 106 | 107 | result = await self.stock_analyzer.run(prompt, deps=deps) 108 | 109 | print(f"Successfully analyzed {self.ticker}") 110 | 111 | # Return the result object directly so the parser can extract token usage 112 | return result 113 | except Exception as e: 114 | print(f"Error analyzing stock {self.ticker}: {str(e)}") 115 | # Return error in a format that can be properly handled 116 | return {"error": f"Failed to analyze stock: {str(e)}"} 117 | 118 | if __name__ == "__main__": 119 | # Define input data 120 | new_input_data = { 121 | "workflow": "structured_output", 122 | # "model": "gpt-4o-mini", 123 | "model": "gpt-4.1-nano", 124 | "framework": "pydantic_agents", 125 | "llm_provider": "openai", 126 | "workflow_input_data": { 127 | "ticker": "AAPL" 128 | } 129 | } 130 | 131 | # Create and run the stock analyzer 132 | start_time = time.time() 133 | 134 | import asyncio 135 | analyzer = PydanticStructuredOutput(input_data=new_input_data) 136 | result = asyncio.run(analyzer.run()) 137 | 138 | if isinstance(result, dict) and "error" in result: 139 | print(f"Error: {result['error']}") 140 | else: 141 | try: 142 | # Use model_dump() instead of dict() for Pydantic v2 compatibility 143 | result_dict = result.output.model_dump() if hasattr(result.output, 'model_dump') else result.output.dict() 144 | 145 | # Print human-readable version 146 | print("\n" + "="*50) 147 | print(f"INVESTMENT ANALYSIS FOR {new_input_data['workflow_input_data']['ticker']}") 148 | print("="*50) 149 | 150 | print("\n📝 REASONING:") 151 | print(result_dict['reasoning']) 152 | 153 | print(f"\n⭐ OVERALL RATING: {result_dict['rating']}/10") 154 | 155 | print("\n📊 RELEVANT KPIs:") 156 | for kpi in result_dict['relevant_kpis']: 157 | print(f" • {kpi['key']}: {kpi['rating']}/10") 158 | 159 | print("\n🔍 IMPROVEMENT REQUIREMENTS:") 160 | print(result_dict['improvement_requirements']) 161 | 162 | # Print token usage 163 | if hasattr(result, 'usage'): 164 | usage = result.usage() 165 | print("\n📊 TOKEN USAGE:") 166 | print(f" • Request tokens: {usage.request_tokens}") 167 | print(f" • Response tokens: {usage.response_tokens}") 168 | print(f" • Total tokens: {usage.total_tokens}") 169 | 170 | print("\n" + "="*50) 171 | except Exception as e: 172 | print(f"Error processing result: {str(e)}") 173 | 174 | end_time = time.time() 175 | print(f"Time taken: {end_time - start_time:.2f} seconds") 176 | -------------------------------------------------------------------------------- /structured_data/warren_buffet_investement_principles.txt: -------------------------------------------------------------------------------- 1 | Value investing: Buffett looks for undervalued companies - those trading below their intrinsic value. He aims to buy great businesses at fair prices, rather than fair businesses at great prices. 2 | Long-term perspective: He invests with a long-term outlook, often holding stocks for decades. This aligns with his belief that the stock market is unpredictable in the short term but tends to rise over the long term. 3 | Understanding the business: Buffett only invests in companies and industries he thoroughly understands. This principle helps him better assess the company's potential and risks. 4 | Competitive advantage: He looks for companies with a strong "economic moat" - a sustainable competitive advantage that protects the company from competitors. 5 | Quality management: Buffett places high importance on honest, competent management teams that act in the best interests of shareholders. 6 | Financial health: He prefers companies with strong balance sheets, consistent earnings, high return on equity, and low debt. 7 | Predictable earnings: Buffett favors businesses with steady and predictable earnings rather than those in volatile or cyclical industries. 8 | Margin of safety: He always aims to buy stocks with a significant margin of safety - the difference between the intrinsic value of a stock and its market price. 9 | Dividend policy: While not a strict requirement, Buffett often favors companies that pay dividends and have a history of increasing them. 10 | Circle of competence: He sticks to investments within his "circle of competence" - areas where he has deep knowledge and expertise. -------------------------------------------------------------------------------- /task_delegation.py: -------------------------------------------------------------------------------- 1 | from langchain_groq import ChatGroq 2 | import warnings 3 | warnings.filterwarnings('ignore') 4 | from crewai import Agent, Task, Crew 5 | from dotenv import load_dotenv 6 | import os 7 | 8 | load_dotenv() 9 | 10 | GROQ_LLM = ChatGroq( 11 | model="llama3-70b-8192" 12 | ) 13 | 14 | # os.environ["OPENAI_MODEL_NAME"] = 'gpt-3.5-turbo' 15 | os.environ["OPENAI_MODEL_NAME"] = 'gpt-4o' 16 | 17 | teacher = Agent( 18 | role="second grade teacher", 19 | goal="guide the student to the right answer", 20 | backstory=( 21 | "you help the student to figure out the right answer \n" 22 | "you give little hints \n" 23 | "you give very short answers, which are maxium 1 sentence long \n" 24 | ), 25 | allow_delegation=True, 26 | # llm = GROQ_LLM, 27 | verbose=True, 28 | ) 29 | 30 | student = Agent( 31 | role="second grade student", 32 | goal="guess the right answer of the teacher", 33 | backstory=( 34 | "you are trying to guess the right answer of the question of the teacher \n" 35 | "your answer is only one word or one number long \n" 36 | ), 37 | allow_delegation=False, 38 | # llm = GROQ_LLM, 39 | verbose=True, 40 | ) 41 | 42 | ask_question = Task( 43 | description=( 44 | "let the student guess a number between 1 and 10 \n" 45 | "the number for the student to guess is 8 \n" 46 | "if the student guesses 8, the taks is done" 47 | ), 48 | expected_output=( 49 | "instuctions for the student \n" 50 | ), 51 | agent= teacher 52 | ) 53 | 54 | answer_question = Task( 55 | description=( 56 | "answer the questions of the teacher \n" 57 | "follow the instructions of the teacher \n" 58 | ), 59 | expected_output="a number between 1 and 10", 60 | agent= student 61 | ) 62 | 63 | crew = Crew( 64 | agents=[teacher, student], 65 | tasks=[ask_question, answer_question], 66 | verbose=2, 67 | memory=True 68 | ) 69 | 70 | 71 | result = crew.kickoff() 72 | print(crew.usage_metrics) 73 | 74 | 75 | # try without memory 76 | # try with memory 77 | # try with delegation 78 | # try without delegation 79 | # bring in two students, one only answers 0-10 other 11-20 coordinator has to 80 | # figure out that -------------------------------------------------------------------------------- /tools/tool_yahoo_finance.py: -------------------------------------------------------------------------------- 1 | import yfinance as yf 2 | import pandas as pd 3 | 4 | def get_stock_data(ticker): 5 | """ 6 | Retrieve stock data from Yahoo Finance for a specific ticker, 7 | including key performance indicators. 8 | 9 | Parameters: 10 | ----------- 11 | ticker : str 12 | The stock ticker symbol (e.g., 'AAPL' for Apple). 13 | 14 | Returns: 15 | -------- 16 | list 17 | List of key performance indicators 18 | """ 19 | try: 20 | # Create a Ticker object 21 | stock = yf.Ticker(ticker) 22 | 23 | # Get stock info 24 | info = stock.info 25 | 26 | # Create list of KPIs 27 | kpis = [ 28 | f"Company: {info.get('shortName', 'N/A')}", 29 | f"Sector: {info.get('sector', 'N/A')}", 30 | f"Industry: {info.get('industry', 'N/A')}", 31 | f"Market Cap (B): {round(info.get('marketCap', 0) / 1_000_000_000, 2)}", 32 | f"P/E Ratio: {info.get('trailingPE', 'N/A')}", 33 | f"Forward P/E: {info.get('forwardPE', 'N/A')}", 34 | f"EPS (TTM): {info.get('trailingEps', 'N/A')}", 35 | f"Dividend Yield (%): {round(info.get('dividendYield', 0) * 100, 2) if info.get('dividendYield') else 'N/A'}", 36 | f"Profit Margin (%): {round(info.get('profitMargins', 0) * 100, 2) if info.get('profitMargins') else 'N/A'}", 37 | f"ROE (%): {round(info.get('returnOnEquity', 0) * 100, 2) if info.get('returnOnEquity') else 'N/A'}", 38 | f"Debt to Equity: {info.get('debtToEquity', 'N/A')}", 39 | f"Beta (5Y): {info.get('beta', 'N/A')}", 40 | f"52-Week High: {info.get('fiftyTwoWeekHigh', 'N/A')}", 41 | f"52-Week Low: {info.get('fiftyTwoWeekLow', 'N/A')}", 42 | f"Analyst Rating: {info.get('recommendationKey', 'N/A').capitalize() if info.get('recommendationKey') else 'N/A'}", 43 | f"Target Price: {info.get('targetMeanPrice', 'N/A')}" 44 | ] 45 | 46 | return kpis 47 | 48 | except Exception as e: 49 | print(f"Error retrieving data for {ticker}: {e}") 50 | return [] 51 | 52 | # Example usage 53 | if __name__ == "__main__": 54 | # Get data for Apple (AAPL) 55 | ticker_symbol = "AAPL" 56 | kpis = get_stock_data(ticker_symbol) 57 | 58 | # Print KPIs 59 | print(f"\n===== Key Performance Indicators for {ticker_symbol} =====") 60 | for kpi in kpis: 61 | print(kpi) -------------------------------------------------------------------------------- /webDev/constants.py: -------------------------------------------------------------------------------- 1 | demo_img_path = "videos/webDev/model_page.png" 2 | recent_state_img_path = "videos/webDev/recent_screenshot.png" 3 | html_code_path="videos/webDev/recent_state.html" 4 | ini_description_path="videos/webDev/ini_description.txt" 5 | recent_state_analysis_path="videos/webDev/recent_state_analysis.txt" -------------------------------------------------------------------------------- /webDev/ini_description.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 1. Initial Analysis: 4 | - The website features a simple design with a focus on central elements. The primary focus is on an icon and four interactive boxes with text. 5 | 6 | 2. Overall Layout Description: 7 | - Number of Columns: One central column 8 | - Positioning: 9 | - Header: Not explicitly visible 10 | - Navigation: Not explicitly visible 11 | - Main Content Area: Centered vertically and horizontally 12 | - Sidebar: None 13 | - Footer: Present at the bottom 14 | - Grid systems: Single-column layout with elements centrally aligned. 15 | 16 | 3. Visual Elements Detail: 17 | - Logo/Icon: 18 | - Positioned centrally in the upper-middle section. 19 | - Size: Medium 20 | - Color: White 21 | - Shape: Circular, spiral-like design 22 | 23 | - Interactive Boxes (4 total): 24 | - Size: Medium 25 | - Position: Horizontally aligned below the logo 26 | - Colors: 27 | - Box Background: Dark gray (#1E1E1E) 28 | - Text Color: White 29 | - Icon Colors: Blue, Purple, Yellow, Blue (left to right) 30 | - Shapes: Rounded corners 31 | - Hover effect: Not visible 32 | 33 | 4. Text Content: 34 | - Interactive Box 1: "Zeichne mein Haustier als Zeichentrickfigur" 35 | - Interactive Box 2: "Wähle ein fotogenes Outfit aus" 36 | - Interactive Box 3: "Neue Freunde nach dem Umzug" 37 | - Interactive Box 4: "Frage mich nach Hauptstädten" 38 | - Footer Input: "Sende eine Nachricht an ChatGPT" 39 | - Disclaimer Text: "ChatGPT kann Fehler machen. Überprüfe wichtige Informationen." 40 | 41 | 5. CSS and Styling Details: 42 | - Fonts: Sans-serif (not specified) 43 | - Font Sizes: Regular 44 | - Text Alignment: Centered within elements 45 | - Spacing: Equal spacing between the interactive boxes 46 | - Padding and Margins: Standard for central alignment 47 | - Other Details: Background is dark gray (#202123), creating high contrast with white text. 48 | 49 | 6. Structured Sections: 50 |
51 | - Not visible 52 | 53 | 54 | - Not visible 55 | 56 |
57 | - Logo/Icon centrally positioned 58 | - Four interactive text boxes horizontally aligned 59 | 60 | 61 | - N/A 62 | 63 |