Skip to content

Commit ba26916

Browse files
lkk12014402a32543254
authored andcommitted
Add deep research agent (opea-project#2117)
Co-authored-by: kaokao <[email protected]> Signed-off-by: alexsin368 <[email protected]>
1 parent 32c39db commit ba26916

File tree

11 files changed

+457
-0
lines changed

11 files changed

+457
-0
lines changed

DeepResearchAgent/Dockerfile

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Copyright (C) 2025 Intel Corporation
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
ARG IMAGE_REPO=opea
5+
ARG BASE_TAG=latest
6+
FROM $IMAGE_REPO/comps-base:$BASE_TAG
7+
8+
COPY ./deep_researcher.yaml $HOME/deep_researcher.yaml
9+
COPY ./utils.py $HOME/utils.py
10+
COPY ./requirements.txt $HOME/requirements.txt
11+
COPY ./research_agent.py $HOME/research_agent.py
12+
13+
USER root
14+
ARG uvpip='uv pip install --system --no-cache-dir'
15+
RUN pip install --no-cache-dir --upgrade pip setuptools uv && \
16+
$uvpip -r requirements.txt
17+
18+
USER user
19+
20+
ENTRYPOINT ["python", "research_agent.py"]

DeepResearchAgent/README.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Deep Research Agent Application
2+
3+
Deep Research Agents are a new class of autonomous AI systems designed to perform complex, multi-step research tasks that typically require human-level reasoning, planning, and synthesis.
4+
5+
## Overview
6+
7+
In this application, we leverage the deep research agent implementation of [langchain-ai/open_deep_research](https://github.com/langchain-ai/open_deep_research), and deploy it on the Intel platform with opea microserice.
8+
9+
![Architecture Overview](assets/img/opea-deep-research-agent.png)
10+
11+
## Setup Deployment Environment
12+
13+
```
14+
# get your TAVILY_API_KEY from https://app.tavily.com/
15+
export TAVILY_API_KEY=""
16+
# get your HuggingFace Access Token from https://huggingface.co/docs/transformers.js/en/guides/private#step-1-generating-a-user-access-token
17+
export HF_TOKEN=""
18+
19+
# set proxy if needed by your machine
20+
export http_proxy=""
21+
export https_proxy=""
22+
export no_proxy=""
23+
24+
25+
source ./set_env.sh
26+
```
27+
28+
## Deploy the Services Using Docker Compose
29+
30+
To deploy the Deep Research Agent services, execute the docker compose up command with the appropriate arguments. For a default deployment, execute:
31+
32+
```
33+
docker compose -f docker_compose/intel/hpu/gaudi/compose.yaml up -d
34+
35+
```
36+
37+
## Validate Microservice
38+
39+
```shell
40+
curl http://${host_ip}:8022/v1/deep_research_agent \
41+
-X POST \
42+
-d '{"question":"What is Deep Learning?"}' \
43+
-H 'Content-Type: application/json'
44+
```
52.8 KB
Loading
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Copyright (C) 2025 Intel Corporation
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
agent:
5+
type: langchain_deep_researcher
6+
search_api: "tavily"
7+
planner_provider: "openai"
8+
planner_model: "meta-llama/Llama-3.3-70B-Instruct"
9+
writer_provider: "openai"
10+
writer_model: "meta-llama/Llama-3.3-70B-Instruct"
11+
max_search_depth: 2
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Copyright (C) 2024 Intel Corporation
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
5+
x-common-environment:
6+
&common-env
7+
no_proxy: ${no_proxy}
8+
http_proxy: ${http_proxy}
9+
https_proxy: ${https_proxy}
10+
11+
x-common-agent-environment:
12+
&common-agent-env
13+
<<: *common-env
14+
HF_TOKEN: ${HF_TOKEN}
15+
model: ${LLM_MODEL_ID}
16+
TAVILY_API_KEY: ${TAVILY_API_KEY}
17+
OPENAI_API_KEY: ${OPENAI_API_KEY}
18+
OPENAI_BASE_URL: ${OPENAI_BASE_URL}
19+
20+
services:
21+
22+
vllm-service:
23+
image: ${REGISTRY:-opea}/vllm-gaudi:${TAG:-latest}
24+
container_name: vllm-gaudi-server
25+
ports:
26+
- "8000:8000"
27+
volumes:
28+
- ${HF_CACHE_DIR:-./data}:/data
29+
environment:
30+
<<: *common-env
31+
HF_TOKEN: ${HF_TOKEN}
32+
HF_HOME: ./data
33+
HABANA_VISIBLE_DEVICES: all
34+
OMPI_MCA_btl_vader_single_copy_mechanism: none
35+
LLM_MODEL_ID: ${LLM_MODEL_ID}
36+
VLLM_TORCH_PROFILER_DIR: "/mnt"
37+
VLLM_SKIP_WARMUP: true
38+
PT_HPU_ENABLE_LAZY_COLLECTIVES: true
39+
healthcheck:
40+
test: ["CMD-SHELL", "curl -f http://$HOST_IP:8000/health || exit 1"]
41+
interval: 10s
42+
timeout: 10s
43+
retries: 100
44+
runtime: habana
45+
cap_add:
46+
- SYS_NICE
47+
ipc: host
48+
command: --model ${LLM_MODEL_ID} --tensor-parallel-size ${NUM_CARDS} --host 0.0.0.0 --port 8000 --max-seq-len-to-capture $MAX_LEN
49+
50+
deep-research-agent-server:
51+
image: ${REGISTRY:-opea}/deep-research-agent:${TAG:-latest}
52+
container_name: deep-research-agent-server
53+
depends_on:
54+
- vllm-service
55+
ports:
56+
- "8022:8022"
57+
ipc: host
58+
environment:
59+
<<: *common-agent-env
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#!/usr/bin/env bash
2+
3+
# Copyright (C) 2024 Intel Corporation
4+
# SPDX-License-Identifier: Apache-2.0
5+
6+
# Navigate to the parent directory and source the environment
7+
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd)
8+
9+
pushd "$SCRIPT_DIR/../../../../../" > /dev/null
10+
source .set_env.sh
11+
popd > /dev/null
12+
13+
# Function to check if a variable is set
14+
check_var() {
15+
local var_name="$1"
16+
local var_value="${!var_name}"
17+
if [ -z "${var_value}" ]; then
18+
echo "Error: ${var_name} is not set. Please set ${var_name}."
19+
return 1 # Return an error code but do not exit the script
20+
fi
21+
}
22+
23+
# Check critical variables
24+
check_var "HF_TOKEN"
25+
export ip_address=$(hostname -I | awk '{print $1}')
26+
27+
# VLLM configuration
28+
export VLLM_PORT="${VLLM_PORT:-8000}"
29+
export VLLM_VOLUME="${VLLM_VOLUME:-/data2/huggingface}"
30+
export VLLM_IMAGE="${VLLM_IMAGE:-opea/vllm-gaudi:latest}"
31+
export LLM_MODEL_ID="${LLM_MODEL_ID:-meta-llama/Llama-3.3-70B-Instruct}"
32+
export MAX_LEN="${MAX_LEN:-131072}"
33+
export NUM_CARDS="${NUM_CARDS:-4}"
34+
export HF_CACHE_DIR="${HF_CACHE_DIR:-"./data"}"
35+
export OPENAI_BASE_URL="http://${ip_address}:8000/v1"
36+
export OPENAI_API_KEY="empty"
37+
export no_proxy=${no_proxy}
38+
export http_proxy=${http_proxy}
39+
export https_proxy=${https_proxy}
40+
41+
42+
# Hugging Face API token
43+
export HF_TOKEN="${HF_TOKEN}"
44+
45+
# API keys
46+
check_var "TAVILY_API_KEY"
47+
export TAVILY_API_KEY="${TAVILY_API_KEY}"
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Copyright (C) 2024 Intel Corporation
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
services:
5+
deep-research-agent:
6+
build:
7+
args:
8+
IMAGE_REPO: ${REGISTRY}
9+
BASE_TAG: ${TAG}
10+
http_proxy: ${http_proxy}
11+
https_proxy: ${https_proxy}
12+
no_proxy: ${no_proxy}
13+
context: ../
14+
dockerfile: ./Dockerfile
15+
image: ${REGISTRY:-opea}/deep-research-agent:${TAG:-latest}
16+
vllm-gaudi:
17+
build:
18+
context: vllm-fork
19+
dockerfile: Dockerfile.hpu
20+
extends: deep-research-agent
21+
image: ${REGISTRY:-opea}/vllm-gaudi:${TAG:-latest}

DeepResearchAgent/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
open_deep_research # https://github.com/langchain-ai/open_deep_research
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Copyright (C) 2024 Intel Corporation
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
import argparse
5+
import json
6+
import os
7+
import re
8+
from typing import List, Union
9+
10+
from comps import opea_microservices, register_microservice
11+
from comps.cores.telemetry.opea_telemetry import opea_telemetry
12+
from pydantic import BaseModel
13+
from utils import create_agent
14+
15+
config_path = os.path.join(os.path.dirname(__file__), "deep_researcher.yaml")
16+
agent = create_agent(config_path)
17+
18+
19+
class SimpleRequest(BaseModel):
20+
question: Union[str, List[str]]
21+
22+
23+
@register_microservice(
24+
name="opea_service@deep_research_agent",
25+
endpoint="/v1/deep_research_agent",
26+
host="0.0.0.0",
27+
port=8022,
28+
)
29+
@opea_telemetry
30+
async def run(request: SimpleRequest):
31+
32+
question = f"Question: {request.question}"
33+
34+
result = await agent(question)
35+
36+
return result
37+
38+
39+
if __name__ == "__main__":
40+
opea_microservices["opea_service@deep_research_agent"].start()
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
#!/bin/bash
2+
# Copyright (C) 2024 Intel Corporation
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
set -xe
6+
IMAGE_REPO=${IMAGE_REPO:-"opea"}
7+
IMAGE_TAG=${IMAGE_TAG:-"latest"}
8+
echo "REGISTRY=IMAGE_REPO=${IMAGE_REPO}"
9+
echo "TAG=IMAGE_TAG=${IMAGE_TAG}"
10+
export REGISTRY=${IMAGE_REPO}
11+
export TAG=${IMAGE_TAG}
12+
export MODEL_CACHE=${model_cache:-"./data"}
13+
export HF_TOKEN=${HF_TOKEN}
14+
export TAVILY_API_KEY=${TAVILY_API_KEY}
15+
16+
WORKPATH=$(dirname "$PWD")
17+
LOG_PATH="$WORKPATH/tests"
18+
ip_address=$(hostname -I | awk '{print $1}')
19+
20+
function build_docker_images() {
21+
opea_branch=${opea_branch:-"main"}
22+
cd $WORKPATH/docker_image_build
23+
git clone --depth 1 --branch ${opea_branch} https://github.com/opea-project/GenAIComps.git
24+
pushd GenAIComps
25+
echo "GenAIComps test commit is $(git rev-parse HEAD)"
26+
docker build --no-cache -t ${REGISTRY}/comps-base:${TAG} --build-arg https_proxy=$https_proxy --build-arg http_proxy=$http_proxy -f Dockerfile .
27+
popd && sleep 1s
28+
git clone https://github.com/HabanaAI/vllm-fork.git && cd vllm-fork
29+
VLLM_FORK_VER=v0.6.6.post1+Gaudi-1.20.0
30+
git checkout ${VLLM_FORK_VER} &> /dev/null && cd ../
31+
32+
echo "Build all the images with --no-cache, check docker_image_build.log for details..."
33+
docker compose -f build.yaml build --no-cache > ${LOG_PATH}/docker_image_build.log
34+
35+
docker images && sleep 1s
36+
}
37+
38+
function start_services() {
39+
cd $WORKPATH/docker_compose/intel/hpu/gaudi
40+
source set_env.sh
41+
42+
# Start Docker Containers
43+
docker compose -f compose.yaml up -d --quiet-pull > ${LOG_PATH}/start_services_with_compose.log
44+
n=0
45+
until [[ "$n" -ge 200 ]]; do
46+
echo "n=$n"
47+
docker logs vllm-gaudi-server > vllm_service_start.log 2>&1
48+
if grep -q "Application startup complete" vllm_service_start.log; then
49+
break
50+
fi
51+
sleep 5s
52+
n=$((n+1))
53+
done
54+
}
55+
56+
function validate_service() {
57+
local URL="$1"
58+
local EXPECTED_RESULT="$2"
59+
local SERVICE_NAME="$3"
60+
local DOCKER_NAME="$4"
61+
local INPUT_DATA="$5"
62+
63+
local HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X POST -d "$INPUT_DATA" -H 'Content-Type: application/json' "$URL")
64+
if [ "$HTTP_STATUS" -eq 200 ]; then
65+
echo "[ $SERVICE_NAME ] HTTP status is 200. Checking content..."
66+
67+
local CONTENT=$(curl -s -X POST -d "$INPUT_DATA" -H 'Content-Type: application/json' "$URL" | tee ${LOG_PATH}/${SERVICE_NAME}.log)
68+
69+
if echo "$CONTENT" | grep -q "$EXPECTED_RESULT"; then
70+
echo "[ $SERVICE_NAME ] Content is as expected."
71+
else
72+
echo "[ $SERVICE_NAME ] Content does not match the expected result: $CONTENT"
73+
docker logs ${DOCKER_NAME} >> ${LOG_PATH}/${SERVICE_NAME}.log
74+
exit 1
75+
fi
76+
else
77+
echo "[ $SERVICE_NAME ] HTTP status is not 200. Received status was $HTTP_STATUS"
78+
docker logs ${DOCKER_NAME} >> ${LOG_PATH}/${SERVICE_NAME}.log
79+
exit 1
80+
fi
81+
sleep 1s
82+
}
83+
84+
function validate_microservices() {
85+
# Check if the microservices are running correctly.
86+
87+
validate_service \
88+
"${ip_address}:8022/v1/deep_research_agent" \
89+
"deep" \
90+
"deep-research-agent" \
91+
"deep-research-agent-server" \
92+
'{"question": "what is the deep learning?"}'
93+
}
94+
95+
96+
function stop_docker() {
97+
cd $WORKPATH/docker_compose/intel/hpu/gaudi
98+
docker compose -f compose.yaml down
99+
}
100+
101+
function main() {
102+
103+
echo "::group::stop_docker"
104+
stop_docker
105+
echo "::endgroup::"
106+
107+
echo "::group::build_docker_images"
108+
if [[ "$IMAGE_REPO" == "opea" ]]; then build_docker_images; fi
109+
echo "::endgroup::"
110+
111+
echo "::group::start_services"
112+
start_services
113+
echo "::endgroup::"
114+
115+
echo "::group::validate_microservices"
116+
validate_microservices
117+
echo "::endgroup::"
118+
119+
echo "::group::stop_docker"
120+
stop_docker
121+
echo "::endgroup::"
122+
123+
docker system prune -f
124+
125+
}
126+
127+
main

0 commit comments

Comments
 (0)