ofermend commited on
Commit
95517e6
·
1 Parent(s): 1770a97
Files changed (5) hide show
  1. README.md +2 -2
  2. agent.py +13 -129
  3. app.py +1 -1
  4. requirements.txt +1 -1
  5. st_app.py +8 -8
README.md CHANGED
@@ -1,5 +1,5 @@
1
  ---
2
- title: Finance assistant
3
  emoji: 🐨
4
  colorFrom: indigo
5
  colorTo: indigo
@@ -7,7 +7,7 @@ sdk: docker
7
  app_port: 8501
8
  pinned: false
9
  license: apache-2.0
10
- short_description: Finance chatbot using vectara-agentic
11
  ---
12
 
13
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: UCSF Ortho Demo
3
  emoji: 🐨
4
  colorFrom: indigo
5
  colorTo: indigo
 
7
  app_port: 8501
8
  pinned: false
9
  license: apache-2.0
10
+ short_description: Ask questions about UCSF Orthopedics
11
  ---
12
 
13
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
agent.py CHANGED
@@ -1,154 +1,38 @@
1
  import os
2
- import pandas as pd
3
- import requests
4
- from pydantic import Field, BaseModel
5
-
6
  from omegaconf import OmegaConf
7
 
8
  from vectara_agentic.agent import Agent
9
- from vectara_agentic.tools import ToolsFactory, VectaraToolFactory
10
 
11
  from dotenv import load_dotenv
12
  load_dotenv(override=True)
13
 
14
-
15
- tickers = {
16
- "C": "Citigroup",
17
- "COF": "Capital One",
18
- "JPM": "JPMorgan Chase",
19
- "AAPL": "Apple Computer",
20
- "GOOG": "Google",
21
- "AMZN": "Amazon",
22
- "SNOW": "Snowflake",
23
- "TEAM": "Atlassian",
24
- "TSLA": "Tesla",
25
- "NVDA": "Nvidia",
26
- "MSFT": "Microsoft",
27
- "AMD": "Advanced Micro Devices",
28
- "INTC": "Intel",
29
- "NFLX": "Netflix",
30
- "STT": "State Street",
31
- "BK": "Bank of New York Mellon",
32
- }
33
- years = range(2015, 2025)
34
  initial_prompt = "How can I help you today?"
35
 
36
- def create_assistant_tools(cfg):
37
-
38
- def get_company_info() -> list[str]:
39
- """
40
- Returns a dictionary of companies you can query about. Always check this before using any other tool.
41
- The output is a dictionary of valid ticker symbols mapped to company names.
42
- You can use this to identify the companies you can query about, and their ticker information.
43
- """
44
- return tickers
45
-
46
- def get_valid_years() -> list[str]:
47
- """
48
- Returns a list of the years for which financial reports are available.
49
- Always check this before using any other tool.
50
- """
51
- return years
52
-
53
- # Tool to get the income statement for a given company and year using the FMP API
54
- def fmp_income_statement(
55
- ticker: str = Field(description="the ticker symbol of the company."),
56
- year: int = Field(description="the year for which to get the income statement."),
57
- ) -> str:
58
- """
59
- Get the income statement for a given company and year using the FMP (https://financialmodelingprep.com) API.
60
- Returns a dictionary with the income statement data. All data is in USD, but you can convert it to more compact form like K, M, B.
61
- """
62
- fmp_api_key = os.environ.get("FMP_API_KEY", None)
63
- if fmp_api_key is None:
64
- return "FMP_API_KEY environment variable not set. This tool does not work."
65
- url = f"https://financialmodelingprep.com/api/v3/income-statement/{ticker}?apikey={fmp_api_key}"
66
- response = requests.get(url)
67
- if response.status_code == 200:
68
- data = response.json()
69
- income_statement = pd.DataFrame(data)
70
- if len(income_statement) == 0 or "date" not in income_statement.columns:
71
- return "No data found for the given ticker symbol."
72
- income_statement["date"] = pd.to_datetime(income_statement["date"])
73
- income_statement_specific_year = income_statement[
74
- income_statement["date"].dt.year == int(year)
75
- ]
76
- values_dict = income_statement_specific_year.to_dict(orient="records")[0]
77
- return f"Financial results: {', '.join([f'{key}={value}' for key, value in values_dict.items() if key not in ['date', 'cik', 'link', 'finalLink']])}"
78
-
79
- return f"FMP API returned error {response.status_code}. This tool does not work."
80
-
81
- class QueryTranscriptsArgs(BaseModel):
82
- query: str = Field(..., description="The user query, always in the form of a question", examples=["what are the risks reported?", "who are the competitors?"])
83
- year: int | str = Field(..., description=f"The year this query relates to. An integer between {min(years)} and {max(years)} or a string specifying a condition on the year (example: '>2020').")
84
- ticker: str = Field(..., description=f"The company ticker this query relates to. Must be a valid ticket symbol from the list {list(tickers.keys())}.")
85
-
86
- vec_factory = VectaraToolFactory(vectara_api_key=cfg.api_key,
87
- vectara_customer_id=cfg.customer_id,
88
- vectara_corpus_id=cfg.corpus_id)
89
- summarizer = 'vectara-experimental-summary-ext-2023-12-11-med-omni'
90
- ask_transcripts = vec_factory.create_rag_tool(
91
- tool_name = "ask_transcripts",
92
- tool_description = """
93
- Given a company name and year, responds to a user question about the company, based on analyst call transcripts about the company's financial reports for that year.
94
- You can ask this tool any question about the company including risks, opportunities, financial performance, competitors and more.
95
- """,
96
- tool_args_schema = QueryTranscriptsArgs,
97
- reranker = "multilingual_reranker_v1", rerank_k = 100,
98
- n_sentences_before = 2, n_sentences_after = 2, lambda_val = 0.005,
99
- summary_num_results = 10,
100
- vectara_summarizer = summarizer,
101
- include_citations = True,
102
- )
103
-
104
- tools_factory = ToolsFactory()
105
- return (
106
- [tools_factory.create_tool(tool) for tool in
107
- [
108
- get_company_info,
109
- get_valid_years,
110
- fmp_income_statement,
111
- ]
112
- ] +
113
- tools_factory.financial_tools() +
114
- [ask_transcripts]
115
- )
116
 
117
  def initialize_agent(_cfg, agent_progress_callback=None):
118
- financial_bot_instructions = """
119
- - You are a helpful financial assistant, with expertise in financial reporting, in conversation with a user.
120
- - Use the ask_transcripts tool to answer most questions about the company's financial performance, risks, opportunities, strategy, competitors, and more.
121
- - responses from ask_transcripts are summarized. You don't need to further summarize them.
122
- - Respond in a compact format by using appropriate units of measure (e.g., K for thousands, M for millions, B for billions).
123
- Do not report the same number twice (e.g. $100K and 100,000 USD).
124
- - Always use the 'income_statement' tool to obtain accurate financial data like revenues, expenses, net income, and other financial metrics
125
- for a specific company, for any the year 2020 or later.
126
- - Use the 'fmp_income_statement' tool (with the company ticker and year) to obtain financial data for any year before 2020.
127
- - Always check the 'get_company_info' and 'get_valid_years' tools to validate company and year are valid.
128
- - Do not include URLs unless they are provided in the output of a tool you use.
129
- - When querying a tool for a numeric value or KPI, use a concise and non-ambiguous description of what you are looking for.
130
- - If you calculate a metric, make sure you have all the necessary information to complete the calculation. Don't guess.
131
- """
132
-
133
- agent = Agent(
134
- tools=create_assistant_tools(_cfg),
135
- topic="Financial data, annual reports and 10-K filings",
136
- custom_instructions=financial_bot_instructions,
137
- agent_progress_callback=agent_progress_callback,
138
  )
139
  agent.report()
140
  return agent
141
 
142
 
143
  def get_agent_config() -> OmegaConf:
144
- companies = ", ".join(tickers.values())
145
  cfg = OmegaConf.create({
146
  'customer_id': str(os.environ['VECTARA_CUSTOMER_ID']),
147
  'corpus_id': str(os.environ['VECTARA_CORPUS_ID']),
148
  'api_key': str(os.environ['VECTARA_API_KEY']),
149
  'examples': os.environ.get('QUERY_EXAMPLES', None),
150
- 'demo_name': "finance-chat",
151
- 'demo_welcome': "Financial Assistant demo.",
152
- 'demo_description': f"This assistant can help you with any questions about the financials of several companies:\n\n **{companies}**.\n"
153
  })
154
  return cfg
 
1
  import os
2
+ from typing import Optional
 
 
 
3
  from omegaconf import OmegaConf
4
 
5
  from vectara_agentic.agent import Agent
 
6
 
7
  from dotenv import load_dotenv
8
  load_dotenv(override=True)
9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  initial_prompt = "How can I help you today?"
11
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
13
  def initialize_agent(_cfg, agent_progress_callback=None):
14
+ agent = Agent.from_corpus(
15
+ vectara_customer_id=_cfg.customer_id,
16
+ vectara_corpus_id=_cfg.corpus_id,
17
+ vectara_api_key=_cfg.api_key,
18
+ tool_name="ask_ucsf_ortho",
19
+ data_description="UCSF Orthopedic Website",
20
+ assistant_specialty="UCSF Orthopedic department",
21
+ vectara_summarizer="vectara-summary-ext-24-05-med-omni",
22
+ vectara_reranker="multilingual_reranker_v1",
 
 
 
 
 
 
 
 
 
 
 
23
  )
24
  agent.report()
25
  return agent
26
 
27
 
28
  def get_agent_config() -> OmegaConf:
 
29
  cfg = OmegaConf.create({
30
  'customer_id': str(os.environ['VECTARA_CUSTOMER_ID']),
31
  'corpus_id': str(os.environ['VECTARA_CORPUS_ID']),
32
  'api_key': str(os.environ['VECTARA_API_KEY']),
33
  'examples': os.environ.get('QUERY_EXAMPLES', None),
34
+ 'demo_name': "UCSF Ortho Demo",
35
+ 'demo_welcome': "",
36
+ 'demo_description': "This assistant can help you with any questions about UCSF Orthopedic department."
37
  })
38
  return cfg
app.py CHANGED
@@ -13,6 +13,6 @@ if "feedback_key" not in st.session_state:
13
  st.session_state.feedback_key = 0
14
 
15
  if __name__ == "__main__":
16
- st.set_page_config(page_title="Financial Assistant", layout="wide")
17
  nest_asyncio.apply()
18
  asyncio.run(launch_bot())
 
13
  st.session_state.feedback_key = 0
14
 
15
  if __name__ == "__main__":
16
+ st.set_page_config(page_title="UCSF Ortho Assistant", layout="wide")
17
  nest_asyncio.apply()
18
  asyncio.run(launch_bot())
requirements.txt CHANGED
@@ -6,4 +6,4 @@ streamlit_feedback==0.1.3
6
  uuid==1.30
7
  langdetect==1.0.9
8
  langcodes==3.4.0
9
- vectara-agentic==0.1.22
 
6
  uuid==1.30
7
  langdetect==1.0.9
8
  langcodes==3.4.0
9
+ vectara-agentic==0.1.24
st_app.py CHANGED
@@ -91,12 +91,12 @@ async def launch_bot():
91
  if st.button('Show Logs'):
92
  show_modal()
93
 
94
- st.divider()
95
- st.markdown(
96
- "## How this works?\n"
97
- "This app was built with [Vectara](https://vectara.com).\n\n"
98
- "It demonstrates the use of Agentic RAG functionality with Vectara"
99
- )
100
 
101
  if "messages" not in st.session_state.keys():
102
  reset()
@@ -132,8 +132,8 @@ async def launch_bot():
132
  if st.session_state.prompt:
133
  with st.chat_message("assistant", avatar='🤖'):
134
  st.session_state.status = st.status('Processing...', expanded=False)
135
- res = st.session_state.agent.chat(st.session_state.prompt)
136
- res = escape_dollars_outside_latex(res)
137
  message = {"role": "assistant", "content": res, "avatar": '🤖'}
138
  st.session_state.messages.append(message)
139
  st.markdown(res)
 
91
  if st.button('Show Logs'):
92
  show_modal()
93
 
94
+ # st.divider()
95
+ # st.markdown(
96
+ # "## How this works?\n"
97
+ # "This app was built with [Vectara](https://vectara.com).\n\n"
98
+ # "It demonstrates the use of Agentic RAG functionality with Vectara"
99
+ # )
100
 
101
  if "messages" not in st.session_state.keys():
102
  reset()
 
132
  if st.session_state.prompt:
133
  with st.chat_message("assistant", avatar='🤖'):
134
  st.session_state.status = st.status('Processing...', expanded=False)
135
+ response = st.session_state.agent.chat(st.session_state.prompt)
136
+ res = escape_dollars_outside_latex(response.response)
137
  message = {"role": "assistant", "content": res, "avatar": '🤖'}
138
  st.session_state.messages.append(message)
139
  st.markdown(res)