Text-to-SQL backend
November 23, 2023

Text-to-SQL backend

เมื่อพูดถึง database ก็คงหนีไม่พ้น SQL ภาษาที่เอาไว้ใช้ในการทำงานกับ database ของเรา หลายคนโดนเฉพาะมือใหม่อาจจะเจอปัญหาที่ว่า เราอยากได้ข้อมูลซักชุดแต่ว่ารู้จะเขียน SQL อย่างไรให้ดึงข้อมูลชุดนั้นได้ ทำให้ต้องเสียเวลาไปกับการค้นหา syntax ที่ต้องการ ทำงานให้เวลาในการทำงานเพิ่มขึ้น

แต่ในปัจจุบันนี้การเข้ามาของ GenerativeAI เป็นตัวช่วยให้เราทำงานอะไรหลายๆอย่างได้ง่ายขึ้นมาก ซึ่งหนึ่งในความสามารถที่เราจะเอามานำเสนอวันนี้คือ การเปลี่ยนข้อความให้กลายเป็น sql เพื่อทำงานข้อมูลใน database บทความนี้จะพาทุกคนไปทดลองใช้งาน text to sql เบื้องต้น ตั้งแต่การเตรียม server จนไปถึงการสร้าง api ในการใช้งาน ที่ทุกคนสามารถนำไปปรับใช้กับข้อมูลของตัวเองที่มีอยู่ได้

Setting up AWS EC2 instance

ตัวอย่างนี้เราจะใช้งาน EC2 instance สำหรับการติดตั้ง database และ api backend โดยเราจะใช้งาน EC2 type ที่ต้องการ Ram มากซักหน่อยเพื่อ run ตัว database โดย type ที่แนะนำก็จะเป็น large ขึ้นไปเช่น m5.large, c5.large, r5.large ที่มี spec เบื้องต้นเพียงพอต่อการใช้งาน และ storage ซัก 50GB ขึ้นไป และ OS ที่เลือกใช้เราจะใช้งานเป็น Ubuntu และอย่าลืม allow port สำหรับการเชื่อมต่อให้เรียบร้อยนะครับ ปล.เพื่อการทดสอบ เราอาจจะ allow ทุกอย่างเป็น public ได้ แต่การใช้งานจริงอาจจะต้อง design ส่วนนี้ให้รัดกุมมากยิ่งขึ้น

Installing and configuring Postgres on EC2

มาถึงการติดตั้ง database วิธีที่ง่ายที่สุดแล้วจะแนะนำก็คือการใช้งาน docker เป็นตัวช่วยในการติดตั้ง ดังนั้นเราจึงต้องมี docker ติดตั้งใน EC2 เราซะก่อน โดยใช้คำสั่งดังนี้

ศึกษาข้อมูลเพิ่มเติมได้จาก Install Docker Engine on Ubuntu | Docker Docs

# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

# Add the repository to Apt sources:
echo \
  "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

ทำการติดตั้ง postgres ด้วย docker

docker run --name llm-postgres -e POSTGRES_PASSWORD=mysecretpassword -p 5432:5432 -d postgres

เพียงเท่านี้เราก็จะได้ postgres database พร้อมใช้งานผ่าน port 5432

Setting up FastAPI backend

initial FastAPI

Source code สำหรับบทความนี้เราจะอ้างอิงจาก

GitHub - vultureprime/deploy-ai-model ในตัวอย่าง text-to-sql-openai-postgresSQL ใน aws-example ในตัวอย่างนี้เราจะใช้ FastAPI ในการสร้าง API,  Llamaindex เป็นตัวกลางในการทำ data model และ LLM model ที่เป็น GPT-4 ดังนั้นในการใช้งานจำเป็นต้องการสร้าง API-KEY ของ openai ซะก่อนที่ https://platform.openai.com/

ทำการติดตั้ง python3 library ที่จำเป็นสำหรับ FastAPI

pip install fastapi
pip install "uvicorn[standard]"

สร้างไฟล์ app.py และทำการ initial FastAPI ขึ้นมา

from fastapi import FastAPI
from fastapi.encoders import jsonable_encoder
from fastapi.responses import JSONResponse
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)


@app.get("/helloworld")
async def helloworld():
    return {"message": "Hello World"}

จากตัวอย่าง code จะเป็นการ initial FastAPI project แล้ว enable CORS สำหรับการเชื่อมต่อกับ frontend ให้เรียบร้อย และการสั่ง run จะใช้คำสั่งว่า

uvicorn app:app

เป็นการสั่งให้ FastAPI ที่เราประกาศไว้ในไฟล์ app.py ทำงาน โดย server จะรันที่ port 8000 เป็น default

initial postgres connection

ติดตั้ง library

pip install sqlalchemy
pip install psycopg2-binary
pip install faker
pip install numpy
pip install random

ประกาศ parameter ในการสร้าง connection โดยการดึงข้อมูลจาก ENV เครื่องดังนั้นเราจึงต้องประกาศ ENV ไว้ก่อน

dotenv.load_dotenv()
HOST = os.environ['HOST']
DBPASSWORD = os.environ['DBPASSWORD']
DBUSER = os.environ['DBUSER']
DBNAME = os.environ['DBNAME']

และจาก github ตัวอย่างเรามีการสร้าง API ไว้สำหรับเตรียม table และ ข้อมูลไว้ให้แล้ว ซึ่งเป็นข้อมูลเกี่ยวกับนักเรียน ที่จะมีข้อมูลน้ำหนัก และส่วนสูง ทุกคนสามารถรันตามลำดับเพื่อใส่ข้อมูลลง database ได้เลยไล่ตั้งแต่

/createTable > สร้าง student table
/getInfo > ตรวจสอบข้อมูลของ table
/addRandomData > ใส่ข้อมูลตัวอย่างลงไปที่ table
/getAllData > ดึงข้อมูลที่ใส่เข้าไปออกมาดู
##########################################
/removeTable > ลบ table ที่เราสร้าง

Integrating LlamaIndex and OpenAI

ในที่สุดก็มาถึงจุดสำคัญของเราตัวอย่างนี้แล้ว นั่นคือการนำ GenerativeAI มาใช้งาน โดยสิ่งที่เราใช้จะมี 2 ตัวด้วยกันคือ

  1. Llamaindex ในการทำ data model เป็นตัวกลางระกว่าง database และ LLM
  2. openAI LLM Model สำหรับประมวลผลข้อความ

เริ่มกันที่การติดตั้ง Library Llamaindex

pip install llama_index

ประกาศ ENV สำหรับ openai-key

OPENAI_API_KEY=your_key

ส่วนของการใช้งานจะอยู่ใน function queryWithPrompt หลักการทำงานก็คือการรับ query ในรูปแบบที่เป็น Text จากนั้น Llamaindex จะทำงานร่วมกับ LLM ในการเชื่อมต่อไปยัง database และสร้าง SQL ที่ต้องการกลับมาให้

Deploying and testing the backend

Deploy backend server

การ deploy เราสามารถทำได้หลายวิธีด้วยกัน ตัวอย่างการ deploy ครั้งนี้จะใช้ผ่าน screen นะครับ ซึ่งผมมองว่าเป็นหนึ่งในวิธีที่ใช้งานไม่ยาก และทุกๆคนน่าจะใช้งานกันได้ เริ่มต้นจาก

Step 1: สร้าง session โดยค่า name ให้เราเปลี่ยนเป็นชื่อที่เราต้องการได้

screen -S name

Step 2: เข้าไปยัง folder ของ api

cd path/to/api

Step 3: สั่ง start FastAPI

uvicorn app:app

Step 4: ออกจาก session screen ปัจจุบัน (detach)

Ctrl+a d

เราก็จะได้ server ทำงานอยู่ background สำหรับการใช้งานได้

Testing

เราจะทดสอบกันว่า API ที่เราได้ deploy ไปใช้งานได้หรือไม่โดยเราจะมาดูผลลัพธ์ที่ต้องการกัน

get : /createTable
Response:
{
    "message": "complete"
}
get : /addRandomData
Response:
[
    {
        "id": 279703,
        "name": "Christina",
        "lastname": "Santos",
        "height": 201.53,
        "weight": 68.07
    },
    {
        "id": 798959,
        "name": "Joshua",
        "lastname": "Austin",
        "height": 173.24,
        "weight": 84.42
    },
    {
        "id": 379621,
        "name": "Katherine",
        "lastname": "Rogers",
        "height": 181.93,
        "weight": 72.49
    },
    {
        "id": 97308,
        "name": "Charles",
        "lastname": "Myers",
        "height": 208.58,
        "weight": 95.22
    },
    {
        "id": 728067,
        "name": "Ricky",
        "lastname": "Sanchez",
        "height": 159.26,
        "weight": 67.92
    },
    {
        "id": 85316,
        "name": "Cameron",
        "lastname": "Cole",
        "height": 165.14,
        "weight": 82.45
    },
    {
        "id": 709571,
        "name": "Olivia",
        "lastname": "Kelly",
        "height": 168.78,
        "weight": 94.57
    },
    {
        "id": 755145,
        "name": "Thomas",
        "lastname": "Jones",
        "height": 173.84,
        "weight": 91.53
    },
    {
        "id": 589996,
        "name": "Travis",
        "lastname": "Nguyen",
        "height": 155.49,
        "weight": 50.71
    },
    {
        "id": 741616,
        "name": "Joe",
        "lastname": "Porter",
        "height": 177.83,
        "weight": 90.01
    }
]
get : /queryWithPrompt (ตัวอย่างคำถามที่เราใส่ไป "Write SQL in PostgresSQL format. Get average hight of student.")
Response:
{
    "result": "The average height of students is approximately 176.56 cm.",
    "SQL Query": "SELECT AVG(height) FROM students;"
}

ทดลอง query ผ่าน PGadmin

Setting up AWS API Gateway

ปิดท้ายด้วยการนำ API ที่ได้ไปทำการเชื่อต่อกับ API Gateway สำหรับการนำไปใช้งาน เพื่อที่เราจะได้ทำการ manage การใช้งานต่างๆได้เพิ่มเติมโดยที่ลดงาน coding ลงไป เช่นการเพิ่ม Authentication เป็นต้น อ่านข้อมูลเพิ่มเติมได้ที่ API Gateway · VulturePrime

ทิ้งท้ายบทความสำหรับ Text2SQL

Text-to-SQL frontend

Text-to-SQL backend

Github frontend

Github backend

FAQ Facebook Group

Aa

© 2023, All Rights Reserved, VulturePrime co., ltd.