File size: 8,269 Bytes
736730d
11b6c0d
 
 
 
 
6d18423
 
5ccc1f4
 
 
 
736730d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27522fd
 
 
 
 
 
736730d
27522fd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
736730d
 
 
27522fd
736730d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# tasks.py
import os

# Set CrewAI storage directory to something writable BEFORE any imports
os.environ["CREWAI_STORAGE_DIR"] = "/tmp/crewai"
os.environ["CREWAI_TELEMETRY_ENABLED"] = "false"
os.environ["CREWAI_DB_PATH"] = "/tmp/crewai/crewai.db"
os.environ["CREWAI_MEMORY_ENABLED"] = "false"
os.environ["CREWAI_TRACING_ENABLED"] = "false"
os.environ["CREWAI_AUTH_ENABLED"] = "false"
os.environ["CREWAI_CREDENTIALS_PATH"] = "/tmp/crewai/credentials"
os.environ["CREWAI_SECURE_STORAGE_PATH"] = "/tmp/crewai/secure"

from utils import search_qdrant, search_news, get_stock_data
from crewai import Task
from agents import finance_knowledge_agent, market_news_agent, stock_analysis_agent, response_refiner_agent

def get_finance_knowledge_task(query):
    """Task for answering general finance knowledge questions."""
    contexts = search_qdrant(query, top_k=3)
    context_text = "\n\n".join([f"Source: {ctx['source']}\nContent: {ctx['text']}" for ctx in contexts])
    is_context_useful = len(context_text) > 50 and any(query.lower() in ctx["text"].lower() for ctx in contexts)

    web_results = search_news(query, max_results=3)
    web_text = "\n\n".join([f"Title: {item['title']}\nSummary: {item['snippet']}" for item in web_results]) if web_results else "No additional info from the web."

    if is_context_useful:
        prompt = f"""
        User query: '{query}'

        You are a Finance Knowledge Expert. Use the following RAG data and web search results to provide a concise, accurate response:

        RAG Data:
        {context_text}

        Web Search Results:
        {web_text}

        ### Instructions:
        - Provide a clear definition or explanation related to the query.
        - Include a practical example or implication if relevant.
        - Cite your sources (e.g., "According to Basics.pdf" or "Based on web search").
        - Keep the response concise, under 200 words.
        """
    else:
        prompt = f"""
        User query: '{query}'

        The RAG data from Qdrant was insufficient:
        {context_text}

        Web search results:
        {web_text}

        ### Instructions:
        - Rely on your own knowledge and web results to provide a concise, accurate response.
        - Note that RAG data was insufficient.
        - Include a practical example or implication if relevant.
        - Cite your sources (e.g., "Based on web search").
        - Keep the response concise, under 200 words.
        """
    return Task(
        description=prompt,
        agent=finance_knowledge_agent,
        expected_output="A concise explanation of the financial concept, with an example and cited sources, under 200 words."
    )

def get_market_news_task(query):
    """Task for summarizing and analyzing market news."""
    news = search_news(query, max_results=3)
    news_text = "\n\n".join([f"Title: {item['title']}\nSummary: {item['snippet']}" for item in news]) if news else "No recent news found."

    prompt = f"""
    User query: '{query}'

    You are a Market News Analyst. Analyze the following news data and provide a summary with actionable insights:

    News Data:
    {news_text}

    ### Instructions:
    - Summarize the key points from the news in 3-4 sentences.
    - Highlight any trends or events that could impact the market.
    - Provide one actionable insight or recommendation for investors.
    - Cite the news sources (e.g., "According to [title]").
    - Keep the response concise, under 200 words.
    """
    return Task(
        description=prompt,
        agent=market_news_agent,
        expected_output="A concise summary of market news, highlighting trends, with an actionable insight, under 200 words."
    )

def get_stock_analysis_task(symbol):
    """Task for analyzing a specific stock with basic technical insights."""
    stock_data = get_stock_data(symbol)
    if "error" in stock_data:
        prompt = f"""
        User query: 'Analyze {symbol}'

        You are a Stock Analysis Expert. There was an error fetching data for the stock:

        Error: {stock_data['error']}

        ### Instructions:
        - Provide a general overview of the stock based on your knowledge.
        - Suggest a potential reason for the error.
        - Recommend an action for the user.
        - Keep the response concise, under 200 words.
        """
    else:
        data_text = f"Price: {stock_data['price']}\nChange: {stock_data['change']} ({stock_data['change_percent']})"
        prompt = f"""
        User query: 'Analyze {symbol}'

        You are a Stock Analysis Expert. Analyze the following stock data with basic technical insights:

        Stock Data:
        {data_text}

        ### Instructions:
        - Interpret the stock's performance and identify any price trend (e.g., upward/downward movement).
        - Identify potential factors influencing the stock (e.g., market trends, sector performance).
        - Provide an investment recommendation (e.g., "Hold", "Buy", "Sell") with a brief rationale.
        - Keep the response concise, under 200 words.
        """
    return Task(
        description=prompt,
        agent=stock_analysis_agent,
        expected_output="A concise analysis of the stock's performance with an investment recommendation, under 150 words."
    )

def get_response_refiner_task(query, initial_response, question_type, rag_note="NO_RAG_NEEDED"):
    """Task for refining and reporting the response."""
    
    # Create a special note for RAG information
    rag_message = ""
    if rag_note == "RAG_NOT_USED":
        rag_message = "Note: No relevant information found in RAG system, web search results were used."
    elif rag_note == "RAG_LIMITED":
        # Don't show any special message when RAG and web search are used together
        rag_message = ""
    elif rag_note == "RAG_SUFFICIENT":
        # Don't show any special message when RAG is sufficient
        rag_message = ""
    
    # Handle out_of_scope case
    if question_type == "out_of_scope":
        prompt = f"""
        User query: '{query}'
        Initial Response: '{initial_response}'
        Question Type: '{question_type}'

        You are a Response Refiner and Reporter. The query is out of scope for a finance assistant.

        ### Instructions:
        - Format as a report indicating the query is out of scope.
        - Do not perform any research or generate additional content.
        - Format as a report:
          **Financial Report for Query: '{query}'**
          - **Summary**: [Explain that the query is not finance-related]
          - **Key Insight**: [Guide the user to ask finance-related questions]
          - **Source/Note**: [Add note indicating no further processing]
        - Keep under 200 words.
        """
        expected_output = f"""
        **Financial Report for Query: '{query}'**
        - **Summary**: This query is not related to finance. I am designed to assist with financial topics like stock analysis, market news, or financial concepts.
        - **Key Insight**: Please try a finance-related question, such as “Analyze META stock performance” or “What is revenue?”
        - **Source/Note**: No further processing performed as query is out of scope.
        """
    else:
        prompt = f"""
        User query: '{query}'
        Initial Response: '{initial_response}'
        Question Type: '{question_type}'
        
        {rag_message}
        
        You are a Response Refiner and Reporter. Refine the initial response and present it in a professional report format.

        ### Instructions:
        - Simplify the language for a general audience.
        - Verify accuracy and logical alignment with the query; add a note if issues are found.
        - Format as a report:
          **Financial Report for Query: '{query}'**
          - **Summary**: [Simplified summary in 3-4 sentences]
          - **Key Insight**: [One key takeaway or recommendation]
          - **Source/Note**: [Cite source or add note]
        - Keep under 200 words.
        """
        expected_output = "A simplified and professionally formatted report, under 200 words."
    
    return Task(
        description=prompt,
        agent=response_refiner_agent,
        expected_output=expected_output
    )