Refactor text2sql. (#1304)

Signed-off-by: Yao, Qing <qing.yao@intel.com>
Signed-off-by: chensuyue <suyue.chen@intel.com>
This commit is contained in:
Yao Qing
2025-01-02 10:52:21 +08:00
committed by GitHub
parent 6169ea4921
commit 72f8079289
7 changed files with 55 additions and 65 deletions

View File

@@ -11,7 +11,7 @@ First of all, you need to build Docker Images locally. This step can be ignored
```bash ```bash
git clone https://github.com/opea-project/GenAIComps.git git clone https://github.com/opea-project/GenAIComps.git
cd GenAIComps cd GenAIComps
docker build --no-cache -t opea/texttosql:comps -f comps/texttosql/langchain/Dockerfile . docker build --no-cache -t opea/text2sql:comps -f comps/text2sql/src/Dockerfile .
``` ```
@@ -21,13 +21,13 @@ Build the frontend Docker image based on react framework via below command:
```bash ```bash
cd GenAIExamples/DBQnA/ui cd GenAIExamples/DBQnA/ui
docker build --no-cache -t opea/texttosql-react-ui:latest -f docker/Dockerfile.react . docker build --no-cache -t opea/text2sql-react-ui:latest -f docker/Dockerfile.react .
``` ```
Then run the command `docker images`, you will have the following Docker Images: Then run the command `docker images`, you will have the following Docker Images:
1. `opea/texttosql:latest` 1. `opea/text2sql:latest`
2. `opea/dbqna-react-ui:latest` 2. `opea/dbqna-react-ui:latest`
## 🚀 Start Microservices ## 🚀 Start Microservices
@@ -62,7 +62,7 @@ export LLM_MODEL_ID="mistralai/Mistral-7B-Instruct-v0.3"
export POSTGRES_USER=postgres export POSTGRES_USER=postgres
export POSTGRES_PASSWORD=testpwd export POSTGRES_PASSWORD=testpwd
export POSTGRES_DB=chinook export POSTGRES_DB=chinook
export texttosql_port=9090 export text2sql_port=9090
``` ```
Note: Please replace with `your_ip` with your external IP address, do not use localhost. Note: Please replace with `your_ip` with your external IP address, do not use localhost.
@@ -90,14 +90,14 @@ We will use [Chinook](https://github.com/lerocha/chinook-database) sample databa
```bash ```bash
docker run --name test-texttosql-postgres --ipc=host -e POSTGRES_USER=${POSTGRES_USER} -e POSTGRES_HOST_AUTH_METHOD=trust -e POSTGRES_DB=${POSTGRES_DB} -e POSTGRES_PASSWORD=${POSTGRES_PASSWORD} -p 5442:5432 -d -v $WORKPATH/comps/texttosql/langchain/chinook.sql:/docker-entrypoint-initdb.d/chinook.sql postgres:latest docker run --name test-text2sql-postgres --ipc=host -e POSTGRES_USER=${POSTGRES_USER} -e POSTGRES_HOST_AUTH_METHOD=trust -e POSTGRES_DB=${POSTGRES_DB} -e POSTGRES_PASSWORD=${POSTGRES_PASSWORD} -p 5442:5432 -d -v $WORKPATH/comps/text2sql/langchain/chinook.sql:/docker-entrypoint-initdb.d/chinook.sql postgres:latest
``` ```
- Start TGI Service - Start TGI Service
```bash ```bash
docker run -d --name="test-texttosql-tgi-endpoint" --ipc=host -p $TGI_PORT:80 -v ./data:/data --shm-size 1g -e HUGGINGFACEHUB_API_TOKEN=${HUGGINGFACEHUB_API_TOKEN} -e HF_TOKEN=${HF_TOKEN} -e model=${model} ghcr.io/huggingface/text-generation-inference:2.1.0 --model-id $model docker run -d --name="test-text2sql-tgi-endpoint" --ipc=host -p $TGI_PORT:80 -v ./data:/data --shm-size 1g -e HUGGINGFACEHUB_API_TOKEN=${HUGGINGFACEHUB_API_TOKEN} -e HF_TOKEN=${HF_TOKEN} -e model=${model} ghcr.io/huggingface/text-generation-inference:2.1.0 --model-id $model
``` ```
- Start Text-to-SQL Service - Start Text-to-SQL Service
@@ -105,7 +105,7 @@ docker run -d --name="test-texttosql-tgi-endpoint" --ipc=host -p $TGI_PORT:80 -v
```bash ```bash
unset http_proxy unset http_proxy
docker run -d --name="test-texttosql-server" --ipc=host -p ${texttosql_port}:8090 --ipc=host -e http_proxy=$http_proxy -e https_proxy=$https_proxy -e TGI_LLM_ENDPOINT=$TGI_LLM_ENDPOINT opea/texttosql:latest docker run -d --name="test-text2sql-server" --ipc=host -p ${text2sql_port}:8090 --ipc=host -e http_proxy=$http_proxy -e https_proxy=$https_proxy -e TGI_LLM_ENDPOINT=$TGI_LLM_ENDPOINT opea/text2sql:latest
``` ```
- Start React UI service - Start React UI service
@@ -141,7 +141,7 @@ curl --location http://${your_ip}:9090/v1/postgres/health \
#### 3.2.2 Invoke the microservice. #### 3.2.2 Invoke the microservice.
```bash ```bash
curl http://${your_ip}:9090/v1/texttosql\ curl http://${your_ip}:9090/v1/text2sql\
-X POST \ -X POST \
-d '{"input_text": "Find the total number of Albums.","conn_str": {"user": "'${POSTGRES_USER}'","password": "'${POSTGRES_PASSWORD}'","host": "'${your_ip}'", "port": "5442", "database": "'${POSTGRES_DB}'"}}' \ -d '{"input_text": "Find the total number of Albums.","conn_str": {"user": "'${POSTGRES_USER}'","password": "'${POSTGRES_PASSWORD}'","host": "'${your_ip}'", "port": "5442", "database": "'${POSTGRES_DB}'"}}' \
-H 'Content-Type: application/json' -H 'Content-Type: application/json'

View File

@@ -15,7 +15,8 @@ services:
no_proxy: ${no_proxy} no_proxy: ${no_proxy}
http_proxy: ${http_proxy} http_proxy: ${http_proxy}
https_proxy: ${https_proxy} https_proxy: ${https_proxy}
HF_TOKEN: ${HF_TOKEN} HF_TOKEN: ${HUGGINGFACEHUB_API_TOKEN}
HUGGINGFACEHUB_API_TOKEN: ${HUGGINGFACEHUB_API_TOKEN}
shm_size: 1g shm_size: 1g
command: --model-id ${LLM_MODEL_ID} command: --model-id ${LLM_MODEL_ID}
@@ -32,19 +33,19 @@ services:
volumes: volumes:
- ./chinook.sql:/docker-entrypoint-initdb.d/chinook.sql - ./chinook.sql:/docker-entrypoint-initdb.d/chinook.sql
texttosql-service: text2sql-service:
image: opea/texttosql:latest image: ${REGISTRY:-opea}/text2sql:${TAG:-latest}
container_name: texttosql-service container_name: text2sql-service
ports: ports:
- "9090:8090" - "9090:8080"
environment: environment:
- TGI_LLM_ENDPOINT=${TGI_LLM_ENDPOINT} - TGI_LLM_ENDPOINT=${TGI_LLM_ENDPOINT}
dbqna-xeon-react-ui-server: dbqna-xeon-react-ui-server:
image: opea/dbqna-react-ui:latest image: ${REGISTRY:-opea}/text2sql-react-ui:${TAG:-latest}
container_name: dbqna-xeon-react-ui-server container_name: dbqna-xeon-react-ui-server
depends_on: depends_on:
- texttosql-service - text2sql-service
ports: ports:
- "5174:80" - "5174:80"
environment: environment:

View File

@@ -2,16 +2,16 @@
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
services: services:
texttosql: text2sql:
build: build:
context: GenAIComps context: GenAIComps
dockerfile: comps/texttosql/langchain/Dockerfile dockerfile: comps/text2sql/src/Dockerfile
args: args:
http_proxy: ${http_proxy} http_proxy: ${http_proxy}
https_proxy: ${https_proxy} https_proxy: ${https_proxy}
no_proxy: ${no_proxy} no_proxy: ${no_proxy}
image: ${REGISTRY:-opea}/texttosql:${TAG:-latest} image: ${REGISTRY:-opea}/text2sql:${TAG:-latest}
texttosql-react-ui: text2sql-react-ui:
build: build:
context: ../ui context: ../ui
dockerfile: ./docker/Dockerfile.react dockerfile: ./docker/Dockerfile.react
@@ -19,4 +19,4 @@ services:
http_proxy: ${http_proxy} http_proxy: ${http_proxy}
https_proxy: ${https_proxy} https_proxy: ${https_proxy}
no_proxy: ${no_proxy} no_proxy: ${no_proxy}
image: ${REGISTRY:-opea}/texttosql-react-ui:${TAG:-latest} image: ${REGISTRY:-opea}/text2sql-react-ui:${TAG:-latest}

View File

@@ -4,66 +4,54 @@
set -xe set -xe
IMAGE_REPO=${IMAGE_REPO:-"opea"}
IMAGE_TAG=${IMAGE_TAG:-"latest"}
echo "REGISTRY=IMAGE_REPO=${IMAGE_REPO}"
echo "TAG=IMAGE_TAG=${IMAGE_TAG}"
export REGISTRY=${IMAGE_REPO}
export TAG=${IMAGE_TAG}
WORKPATH=$(dirname "$PWD") WORKPATH=$(dirname "$PWD")
LOG_PATH="$WORKPATH/tests" LOG_PATH="$WORKPATH/tests"
ip_address=$(hostname -I | awk '{print $1}') ip_address=$(hostname -I | awk '{print $1}')
tgi_port=8008 tgi_port=8008
tgi_volume=$WORKPATH/data
export model="meta-llama/Meta-Llama-3-8B-Instruct"
export HUGGINGFACEHUB_API_TOKEN=${HUGGINGFACEHUB_API_TOKEN}
export POSTGRES_USER=postgres
export POSTGRES_PASSWORD=testpwd
export POSTGRES_DB=chinook
export TEXTTOSQL_PORT=9090
export TGI_LLM_ENDPOINT="http://${ip_address}:${tgi_port}"
function build_docker_images() { function build_docker_images() {
echo $WORKPATH cd $WORKPATH/docker_image_build
OPEAPATH=$(realpath "$WORKPATH/../..") git clone https://github.com/opea-project/GenAIComps.git && cd GenAIComps && git checkout "${opea_branch:-"main"}" && cd ../
echo "Building Text to Sql service..."
cd $OPEAPATH
rm -rf GenAIComps/
git clone https://github.com/opea-project/GenAIComps.git
cd $OPEAPATH/GenAIComps
docker build --no-cache -t opea/texttosql:latest -f comps/texttosql/langchain/Dockerfile .
echo "Building React UI service..."
cd $OPEAPATH/GenAIExamples/DBQnA/ui
docker build --no-cache -t opea/dbqna-react-ui:latest -f docker/Dockerfile.react .
echo "Build all the images with --no-cache, check docker_image_build.log for details..."
docker compose -f build.yaml build --no-cache > ${LOG_PATH}/docker_image_build.log
} }
function start_service() { function start_service() {
cd $WORKPATH/docker_compose/intel/cpu/xeon
export model="mistralai/Mistral-7B-Instruct-v0.3"
export LLM_MODEL_ID=${model}
export HUGGINGFACEHUB_API_TOKEN=${HUGGINGFACEHUB_API_TOKEN}
export POSTGRES_USER=postgres
export POSTGRES_PASSWORD=testpwd
export POSTGRES_DB=chinook
export TEXT2SQL_PORT=9090
export TGI_LLM_ENDPOINT="http://${ip_address}:${tgi_port}"
docker run --name test-texttosql-postgres --ipc=host -e POSTGRES_USER=${POSTGRES_USER} -e POSTGRES_HOST_AUTH_METHOD=trust -e POSTGRES_DB=${POSTGRES_DB} -e POSTGRES_PASSWORD=${POSTGRES_PASSWORD} -p 5442:5432 -d -v $WORKPATH/docker_compose/intel/cpu/xeon/chinook.sql:/docker-entrypoint-initdb.d/chinook.sql postgres:latest # Start Docker Containers
docker compose -f compose.yaml up -d > ${LOG_PATH}/start_services_with_compose.log
docker run -d --name="test-texttosql-tgi-endpoint" --ipc=host -p $tgi_port:80 -v ./data:/data --shm-size 1g -e HUGGINGFACEHUB_API_TOKEN=${HUGGINGFACEHUB_API_TOKEN} -e HF_TOKEN=${HUGGINGFACEHUB_API_TOKEN} -e model=${model} ghcr.io/huggingface/text-generation-inference:2.1.0 --model-id $model
docker run -d --name="test-texttosql-server" --ipc=host -p $TEXTTOSQL_PORT:8090 --ipc=host -e http_proxy=$http_proxy -e https_proxy=$https_proxy -e TGI_LLM_ENDPOINT=$TGI_LLM_ENDPOINT opea/texttosql:latest
# check whether tgi is fully ready. # check whether tgi is fully ready.
n=0 n=0
until [[ "$n" -ge 100 ]] || [[ $ready == true ]]; do until [[ "$n" -ge 100 ]] || [[ $ready == true ]]; do
docker logs test-texttosql-tgi-endpoint > ${LOG_PATH}/tgi.log docker logs tgi-service > ${LOG_PATH}/tgi.log
n=$((n+1)) n=$((n+1))
if grep -q Connected ${LOG_PATH}/tgi.log; then if grep -q Connected ${LOG_PATH}/tgi.log; then
break break
fi fi
sleep 5s sleep 5s
done done
sleep 5s
# Run the UI container
docker run -d --name="test-dbqna-react-ui-server" --ipc=host -p 5174:80 -e no_proxy=$no_proxy -e https_proxy=$https_proxy -e http_proxy=$http_proxy opea/dbqna-react-ui:latest
} }
function validate_microservice() { function validate_microservice() {
result=$(http_proxy="" curl --connect-timeout 5 --max-time 120000 http://${ip_address}:$TEXTTOSQL_PORT/v1/texttosql\ result=$(http_proxy="" curl --connect-timeout 5 --max-time 120000 http://${ip_address}:$TEXT2SQL_PORT/v1/text2sql\
-X POST \ -X POST \
-d '{"input_text": "Find the total number of Albums.","conn_str": {"user": "'${POSTGRES_USER}'","password": "'${POSTGRES_PASSWORD}'","host": "'${ip_address}'", "port": "5442", "database": "'${POSTGRES_DB}'" }}' \ -d '{"input_text": "Find the total number of Albums.","conn_str": {"user": "'${POSTGRES_USER}'","password": "'${POSTGRES_PASSWORD}'","host": "'${ip_address}'", "port": "5442", "database": "'${POSTGRES_DB}'" }}' \
-H 'Content-Type: application/json') -H 'Content-Type: application/json')
@@ -73,8 +61,8 @@ function validate_microservice() {
echo "Result correct." echo "Result correct."
else else
echo "Result wrong. Received was $result" echo "Result wrong. Received was $result"
docker logs test-texttosql-server > ${LOG_PATH}/texttosql.log docker logs text2sql-service > ${LOG_PATH}/text2sql.log
docker logs test-texttosql-tgi-endpoint > ${LOG_PATH}/tgi.log docker logs tgi-service > ${LOG_PATH}/tgi.log
exit 1 exit 1
fi fi
@@ -110,8 +98,8 @@ function validate_frontend() {
} }
function stop_docker() { function stop_docker() {
cid=$(docker ps -aq --filter "name=test-*") cd $WORKPATH/docker_compose/intel/cpu/xeon
if [[ ! -z "$cid" ]]; then docker stop $cid && docker rm $cid && sleep 1s; fi docker compose stop && docker compose rm -f
} }
function main() { function main() {

View File

@@ -21,7 +21,7 @@ const getHostIP = () => {
test('testing api with dynamic host', async () => { test('testing api with dynamic host', async () => {
// Get the dynamic host IP // Get the dynamic host IP
const host = await getHostIP(); const host = await getHostIP();
const endpointUrl = `http://${host}:9090/v1/texttosql`; const endpointUrl = `http://${host}:9090/v1/text2sql`;
const formData = { const formData = {
user: 'postgres', user: 'postgres',
@@ -43,9 +43,10 @@ test('testing api with dynamic host', async () => {
expect(response.status).toBe(200); expect(response.status).toBe(200);
const result = response.data.result; const result = response.data.result;
console.log(result);
expect(result.hasOwnProperty('sql')).toBe(true); expect(result.hasOwnProperty('sql')).toBe(true);
expect(result.hasOwnProperty('output')).toBe(true); expect(result.hasOwnProperty('output')).toBe(true);
expect(result.hasOwnProperty('input')).toBe(true); expect(result.hasOwnProperty('input')).toBe(true);
expect(result.input).toBe(question); expect(result.input.input_text).toBe(question);
}, apiTimeOutInSeconds * 1000); }, apiTimeOutInSeconds * 1000);

View File

@@ -79,7 +79,7 @@ const DBConnect: React.FC = () => {
}; };
let api_response: Record<string, any>; let api_response: Record<string, any>;
api_response = await axios.post(`${TEXT_TO_SQL_URL}/texttosql`, payload); api_response = await axios.post(`${TEXT_TO_SQL_URL}/text2sql`, payload);
setSqlQuery(api_response.data.result.sql); // Assuming the API returns an SQL query setSqlQuery(api_response.data.result.sql); // Assuming the API returns an SQL query
setQueryOutput(api_response.data.result.output); setQueryOutput(api_response.data.result.output);
@@ -163,7 +163,7 @@ const DBConnect: React.FC = () => {
</div> </div>
{/* DBQnA Section */} {/* DBQnA Section */}
<div className={styleClasses.textToSQLSection}> <div className={styleClasses.text2SQLSection}>
<Title order={1}>DBQnA</Title> <Title order={1}>DBQnA</Title>
{isConnected && ( {isConnected && (
<form className={styleClasses.form} onSubmit={handleGenerateSQL}> <form className={styleClasses.form} onSubmit={handleGenerateSQL}>

View File

@@ -19,7 +19,7 @@
} }
.dbConnectSection, .dbConnectSection,
.textToSQLSection { .text2SQLSection {
flex: 1; /* Allow each section to take up equal space */ flex: 1; /* Allow each section to take up equal space */
padding: 20px; padding: 20px;
background-color: white; background-color: white;