Skip to content

Commit 1852e6b

Browse files
minmin-intelrbrugaropre-commit-ci[bot]lkk12014402
authored
Add Finance Agent Example (opea-project#1752)
Signed-off-by: minmin-intel <[email protected]> Signed-off-by: Rita Brugarolas <[email protected]> Signed-off-by: rbrugaro <[email protected]> Co-authored-by: rbrugaro <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: lkk <[email protected]> Co-authored-by: lkk12014402 <[email protected]>
1 parent 72ce335 commit 1852e6b

26 files changed

+2454
-0
lines changed

FinanceAgent/README.md

+145
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
# Finance Agent
2+
3+
## 1. Overview
4+
5+
The architecture of this Finance Agent example is shown in the figure below. The agent has 3 main functions:
6+
7+
1. Summarize long financial documents and provide key points.
8+
2. Answer questions over financial documents, such as SEC filings.
9+
3. Conduct research of a public company and provide an investment report of the company.
10+
11+
![Finance Agent Architecture](assets/finance_agent_arch.png)
12+
13+
The `dataprep` microservice can ingest financial documents in two formats:
14+
15+
1. PDF documents stored locally, such as SEC filings saved in local directory.
16+
2. URLs, such as earnings call transcripts ([example](https://www.fool.com/earnings/call-transcripts/2025/03/06/costco-wholesale-cost-q2-2025-earnings-call-transc/)) and online SEC filings ([example](https://investors.3m.com/financials/sec-filings/content/0000066740-25-000006/0000066740-25-000006.pdf)).
17+
18+
Please note:
19+
20+
1. Each financial document should be about one company.
21+
2. URLs ending in `.htm` are not supported.
22+
23+
## 2. Getting started
24+
25+
### 2.1 Download repos
26+
27+
```bash
28+
mkdir /path/to/your/workspace/
29+
export WORKDIR=/path/to/your/workspace/
30+
genaicomps
31+
genaiexamples
32+
```
33+
34+
### 2.2 Set up env vars
35+
36+
```bash
37+
export HF_CACHE_DIR=/path/to/your/model/cache/
38+
export HF_TOKEN=<you-hf-token>
39+
40+
```
41+
42+
### 2.3 Build docker images
43+
44+
Build docker images for dataprep, agent, agent-ui.
45+
46+
```bash
47+
cd GenAIExamples/FinanceAgent/docker_image_build
48+
docker compose -f build.yaml build --no-cache
49+
```
50+
51+
If deploy on Gaudi, also need to build vllm image.
52+
53+
```bash
54+
cd $WORKDIR
55+
git clone https://github.com/HabanaAI/vllm-fork.git
56+
# get the latest release tag of vllm gaudi
57+
cd vllm-fork
58+
VLLM_VER=$(git describe --tags "$(git rev-list --tags --max-count=1)")
59+
echo "Check out vLLM tag ${VLLM_VER}"
60+
git checkout ${VLLM_VER}
61+
docker build --no-cache -f Dockerfile.hpu -t opea/vllm-gaudi:latest --shm-size=128g . --build-arg https_proxy=$https_proxy --build-arg http_proxy=$http_proxy
62+
```
63+
64+
## 3. Deploy with docker compose
65+
66+
### 3.1 Launch vllm endpoint
67+
68+
Below is the command to launch a vllm endpoint on Gaudi that serves `meta-llama/Llama-3.3-70B-Instruct` model on 4 Gaudi cards.
69+
70+
```bash
71+
cd $WORKDIR/GenAIExamples/FinanceAgent/docker_compose/intel/hpu/gaudi
72+
bash launch_vllm.sh
73+
```
74+
75+
### 3.2 Prepare knowledge base
76+
77+
The commands below will upload some example files into the knowledge base. You can also upload files through UI.
78+
79+
First, launch the redis databases and the dataprep microservice.
80+
81+
```bash
82+
# inside $WORKDIR/GenAIExamples/FinanceAgent/docker_compose/intel/hpu/gaudi/
83+
bash launch_dataprep.sh
84+
```
85+
86+
Validate datat ingest data and retrieval from database:
87+
88+
```bash
89+
python $WORKPATH/tests/test_redis_finance.py --port 6007 --test_option ingest
90+
python $WORKPATH/tests/test_redis_finance.py --port 6007 --test_option get
91+
```
92+
93+
### 3.3 Launch the multi-agent system
94+
95+
```bash
96+
# inside $WORKDIR/GenAIExamples/FinanceAgent/docker_compose/intel/hpu/gaudi/
97+
bash launch_agents.sh
98+
```
99+
100+
### 3.4 Validate agents
101+
102+
FinQA Agent:
103+
104+
```bash
105+
export agent_port="9095"
106+
prompt="What is Gap's revenue in 2024?"
107+
python3 $WORKDIR/GenAIExamples/FinanceAgent/tests/test.py --prompt "$prompt" --agent_role "worker" --ext_port $agent_port
108+
```
109+
110+
Research Agent:
111+
112+
```bash
113+
export agent_port="9096"
114+
prompt="generate NVDA financial research report"
115+
python3 $WORKDIR/GenAIExamples/FinanceAgent/tests/test.py --prompt "$prompt" --agent_role "worker" --ext_port $agent_port --tool_choice "get_current_date" --tool_choice "get_share_performance"
116+
```
117+
118+
Supervisor ReAct Agent:
119+
120+
```bash
121+
export agent_port="9090"
122+
python3 $WORKDIR/GenAIExamples/FinanceAgent/tests/test.py --agent_role "supervisor" --ext_port $agent_port --stream
123+
```
124+
125+
Supervisor ReAct Agent Multi turn:
126+
127+
```bash
128+
python3 $WORKDIR/GenAIExamples/FinanceAgent/tests/test.py --agent_role "supervisor" --ext_port $agent_port --multi-turn --stream
129+
130+
```
131+
132+
## How to interact with the agent system with UI
133+
134+
The UI microservice is launched in the previous step with the other microservices.
135+
To see the UI, open a web browser to `http://${ip_address}:5175` to access the UI. Note the `ip_address` here is the host IP of the UI microservice.
136+
137+
1. `create Admin Account` with a random value
138+
139+
2. use an opea agent endpoint, for example, the `Research Agent` endpoint `http://$ip_address:9096/v1`, which is a openai compatible api
140+
141+
![opea-agent-setting](assets/opea-agent-setting.png)
142+
143+
3. test opea agent with ui
144+
145+
![opea-agent-test](assets/opea-agent-test.png)
57.1 KB
Loading
115 KB
Loading
378 KB
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
# Copyright (C) 2024 Intel Corporation
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
services:
5+
worker-finqa-agent:
6+
image: opea/agent:latest
7+
container_name: finqa-agent-endpoint
8+
volumes:
9+
- ${TOOLSET_PATH}:/home/user/tools/
10+
- ${PROMPT_PATH}:/home/user/prompts/
11+
ports:
12+
- "9095:9095"
13+
ipc: host
14+
environment:
15+
ip_address: ${ip_address}
16+
strategy: react_llama
17+
with_memory: false
18+
recursion_limit: ${recursion_limit_worker}
19+
llm_engine: vllm
20+
HUGGINGFACEHUB_API_TOKEN: ${HUGGINGFACEHUB_API_TOKEN}
21+
llm_endpoint_url: ${LLM_ENDPOINT_URL}
22+
model: ${LLM_MODEL_ID}
23+
temperature: ${TEMPERATURE}
24+
max_new_tokens: ${MAX_TOKENS}
25+
stream: false
26+
tools: /home/user/tools/finqa_agent_tools.yaml
27+
custom_prompt: /home/user/prompts/finqa_prompt.py
28+
require_human_feedback: false
29+
no_proxy: ${no_proxy}
30+
http_proxy: ${http_proxy}
31+
https_proxy: ${https_proxy}
32+
REDIS_URL_VECTOR: $REDIS_URL_VECTOR
33+
REDIS_URL_KV: $REDIS_URL_KV
34+
TEI_EMBEDDING_ENDPOINT: $TEI_EMBEDDING_ENDPOINT
35+
port: 9095
36+
37+
worker-research-agent:
38+
image: opea/agent:latest
39+
container_name: research-agent-endpoint
40+
volumes:
41+
- ${TOOLSET_PATH}:/home/user/tools/
42+
- ${PROMPT_PATH}:/home/user/prompts/
43+
ports:
44+
- "9096:9096"
45+
ipc: host
46+
environment:
47+
ip_address: ${ip_address}
48+
strategy: react_llama
49+
with_memory: false
50+
recursion_limit: ${recursion_limit_worker}
51+
llm_engine: vllm
52+
HUGGINGFACEHUB_API_TOKEN: ${HUGGINGFACEHUB_API_TOKEN}
53+
llm_endpoint_url: ${LLM_ENDPOINT_URL}
54+
model: ${LLM_MODEL_ID}
55+
stream: false
56+
tools: /home/user/tools/research_agent_tools.yaml
57+
custom_prompt: /home/user/prompts/research_prompt.py
58+
require_human_feedback: false
59+
no_proxy: ${no_proxy}
60+
http_proxy: ${http_proxy}
61+
https_proxy: ${https_proxy}
62+
FINNHUB_API_KEY: ${FINNHUB_API_KEY}
63+
FINANCIAL_DATASETS_API_KEY: ${FINANCIAL_DATASETS_API_KEY}
64+
port: 9096
65+
66+
supervisor-react-agent:
67+
image: opea/agent:latest
68+
container_name: supervisor-agent-endpoint
69+
depends_on:
70+
- worker-finqa-agent
71+
# - worker-research-agent
72+
volumes:
73+
- ${TOOLSET_PATH}:/home/user/tools/
74+
- ${PROMPT_PATH}:/home/user/prompts/
75+
ports:
76+
- "9090:9090"
77+
ipc: host
78+
environment:
79+
ip_address: ${ip_address}
80+
strategy: react_llama
81+
with_memory: true
82+
recursion_limit: ${recursion_limit_supervisor}
83+
llm_engine: vllm
84+
HUGGINGFACEHUB_API_TOKEN: ${HUGGINGFACEHUB_API_TOKEN}
85+
llm_endpoint_url: ${LLM_ENDPOINT_URL}
86+
model: ${LLM_MODEL_ID}
87+
temperature: ${TEMPERATURE}
88+
max_new_tokens: ${MAX_TOKENS}
89+
stream: true
90+
tools: /home/user/tools/supervisor_agent_tools.yaml
91+
custom_prompt: /home/user/prompts/supervisor_prompt.py
92+
require_human_feedback: false
93+
no_proxy: ${no_proxy}
94+
http_proxy: ${http_proxy}
95+
https_proxy: ${https_proxy}
96+
WORKER_FINQA_AGENT_URL: $WORKER_FINQA_AGENT_URL
97+
WORKER_RESEARCH_AGENT_URL: $WORKER_RESEARCH_AGENT_URL
98+
DOCSUM_ENDPOINT: $DOCSUM_ENDPOINT
99+
REDIS_URL_VECTOR: $REDIS_URL_VECTOR
100+
REDIS_URL_KV: $REDIS_URL_KV
101+
TEI_EMBEDDING_ENDPOINT: $TEI_EMBEDDING_ENDPOINT
102+
port: 9090
103+
104+
docsum-vllm-gaudi:
105+
image: opea/llm-docsum:latest
106+
container_name: docsum-vllm-gaudi
107+
ports:
108+
- ${DOCSUM_PORT:-9000}:9000
109+
ipc: host
110+
environment:
111+
no_proxy: ${no_proxy}
112+
http_proxy: ${http_proxy}
113+
https_proxy: ${https_proxy}
114+
LLM_ENDPOINT: ${LLM_ENDPOINT}
115+
LLM_MODEL_ID: ${LLM_MODEL_ID}
116+
HF_TOKEN: ${HF_TOKEN}
117+
LOGFLAG: ${LOGFLAG:-False}
118+
MAX_INPUT_TOKENS: ${MAX_INPUT_TOKENS}
119+
MAX_TOTAL_TOKENS: ${MAX_TOTAL_TOKENS}
120+
DocSum_COMPONENT_NAME: ${DocSum_COMPONENT_NAME:-OpeaDocSumvLLM}
121+
restart: unless-stopped
122+
123+
agent-ui:
124+
image: opea/agent-ui:latest
125+
container_name: agent-ui
126+
environment:
127+
host_ip: ${host_ip}
128+
no_proxy: ${no_proxy}
129+
http_proxy: ${http_proxy}
130+
https_proxy: ${https_proxy}
131+
ports:
132+
- "5175:8080"
133+
ipc: host
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# Copyright (C) 2025 Intel Corporation
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
services:
5+
tei-embedding-serving:
6+
image: ghcr.io/huggingface/text-embeddings-inference:cpu-1.5
7+
container_name: tei-embedding-serving
8+
entrypoint: /bin/sh -c "apt-get update && apt-get install -y curl && text-embeddings-router --json-output --model-id ${EMBEDDING_MODEL_ID} --auto-truncate"
9+
ports:
10+
- "${TEI_EMBEDDER_PORT:-10221}:80"
11+
volumes:
12+
- "./data:/data"
13+
shm_size: 1g
14+
environment:
15+
no_proxy: ${no_proxy}
16+
http_proxy: ${http_proxy}
17+
https_proxy: ${https_proxy}
18+
host_ip: ${host_ip}
19+
HF_TOKEN: ${HF_TOKEN}
20+
healthcheck:
21+
test: ["CMD", "curl", "-f", "http://${host_ip}:${TEI_EMBEDDER_PORT}/health"]
22+
interval: 10s
23+
timeout: 6s
24+
retries: 48
25+
26+
redis-vector-db:
27+
image: redis/redis-stack:7.2.0-v9
28+
container_name: redis-vector-db
29+
ports:
30+
- "${REDIS_PORT1:-6379}:6379"
31+
- "${REDIS_PORT2:-8001}:8001"
32+
environment:
33+
- no_proxy=${no_proxy}
34+
- http_proxy=${http_proxy}
35+
- https_proxy=${https_proxy}
36+
healthcheck:
37+
test: ["CMD", "redis-cli", "ping"]
38+
timeout: 10s
39+
retries: 3
40+
start_period: 10s
41+
42+
redis-kv-store:
43+
image: redis/redis-stack:7.2.0-v9
44+
container_name: redis-kv-store
45+
ports:
46+
- "${REDIS_PORT3:-6380}:6379"
47+
- "${REDIS_PORT4:-8002}:8001"
48+
environment:
49+
- no_proxy=${no_proxy}
50+
- http_proxy=${http_proxy}
51+
- https_proxy=${https_proxy}
52+
healthcheck:
53+
test: ["CMD", "redis-cli", "ping"]
54+
timeout: 10s
55+
retries: 3
56+
start_period: 10s
57+
58+
dataprep-redis-finance:
59+
image: ${REGISTRY:-opea}/dataprep:${TAG:-latest}
60+
container_name: dataprep-redis-server-finance
61+
depends_on:
62+
redis-vector-db:
63+
condition: service_healthy
64+
redis-kv-store:
65+
condition: service_healthy
66+
tei-embedding-serving:
67+
condition: service_healthy
68+
ports:
69+
- "${DATAPREP_PORT:-6007}:5000"
70+
environment:
71+
no_proxy: ${no_proxy}
72+
http_proxy: ${http_proxy}
73+
https_proxy: ${https_proxy}
74+
DATAPREP_COMPONENT_NAME: ${DATAPREP_COMPONENT_NAME}
75+
REDIS_URL_VECTOR: ${REDIS_URL_VECTOR}
76+
REDIS_URL_KV: ${REDIS_URL_KV}
77+
TEI_EMBEDDING_ENDPOINT: ${TEI_EMBEDDING_ENDPOINT}
78+
LLM_ENDPOINT: ${LLM_ENDPOINT}
79+
LLM_MODEL: ${LLM_MODEL}
80+
HUGGINGFACEHUB_API_TOKEN: ${HF_TOKEN}
81+
HF_TOKEN: ${HF_TOKEN}
82+
LOGFLAG: true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
2+
# Copyright (C) 2025 Intel Corporation
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
export ip_address=$(hostname -I | awk '{print $1}')
6+
export HUGGINGFACEHUB_API_TOKEN=${HF_TOKEN}
7+
export TOOLSET_PATH=$WORKDIR/GenAIExamples/FinanceAgent/tools/
8+
echo "TOOLSET_PATH=${TOOLSET_PATH}"
9+
export PROMPT_PATH=$WORKDIR/GenAIExamples/FinanceAgent/prompts/
10+
echo "PROMPT_PATH=${PROMPT_PATH}"
11+
export recursion_limit_worker=12
12+
export recursion_limit_supervisor=10
13+
14+
vllm_port=8086
15+
export LLM_MODEL_ID="meta-llama/Llama-3.3-70B-Instruct"
16+
export LLM_ENDPOINT_URL="http://${ip_address}:${vllm_port}"
17+
export TEMPERATURE=0.5
18+
export MAX_TOKENS=4096
19+
20+
export WORKER_FINQA_AGENT_URL="http://${ip_address}:9095/v1/chat/completions"
21+
export WORKER_RESEARCH_AGENT_URL="http://${ip_address}:9096/v1/chat/completions"
22+
23+
export EMBEDDING_MODEL_ID="BAAI/bge-base-en-v1.5"
24+
export TEI_EMBEDDING_ENDPOINT="http://${ip_address}:10221"
25+
export REDIS_URL_VECTOR="redis://${ip_address}:6379"
26+
export REDIS_URL_KV="redis://${ip_address}:6380"
27+
28+
export MAX_INPUT_TOKENS=2048
29+
export MAX_TOTAL_TOKENS=4096
30+
export DocSum_COMPONENT_NAME="OpeaDocSumvLLM"
31+
export DOCSUM_ENDPOINT="http://${ip_address}:9000/v1/docsum"
32+
33+
export FINNHUB_API_KEY=${FINNHUB_API_KEY}
34+
export FINANCIAL_DATASETS_API_KEY=${FINANCIAL_DATASETS_API_KEY}
35+
36+
docker compose -f compose.yaml up -d

0 commit comments

Comments
 (0)