OpenAI with ratelimit backend

ก่อนหน้านี้ Vultureprime ได้มีการทำตัวอย่างการพัฒนา API ร่วมกับตัว generativeAI ไป หนึ่งในต้นทุนที่สำคัญก็หนีไม่พ้นค่า LLM Model ที่หยิบมาใช้งาน ดังนั้นเราจึงจำเป็นต้องมีการจำกัดการใช้งานให้กับ API ของเรา ไม่งั้นกระเป๋าตังค์เราอาจจะฉีกได้ โดยตัวอย่างของเราในวันนี้จะเป็นการใช้งาน feature usage plan ร่วมกับ API key ที่มีอยู่ใน AWS API Gateway ในการสร้าง key เพื่อเรียกใช้งาน API แต่ละตัว

Config usage plan

เริ่มต้นกันที่การสร้าง usage plan ที่เราต้องการก่อน โดยเราจะสร้าง plan ไว้คร่าวๆ 3 plan ด้วยกันคือ 10RequestPerDay,20RequestPerDay,30RequestPerDay และ map เข้ากับ API gateway ที่เราสร้างไว้ ว่าต้องการให้ plan ที่สร้างขึ้นมาใช้งานกับ API Gateway ตัวไหนได้บ้าง

Config API Gateway to use API-key.

ขั้นตอนนี้จะเป็นการ config API Gateway method เพื่อให้ตัวมันรู้ว่าต้องรับ API-Key เข้ามาจึงสามารถส่งต่อ request นั้นไปที่ backend ต่อได้ โดยเราจำเป็นต้อง config ในทุก method ที่ต้องการให้ใช้งาน API Key วิธีการคือ เข้าไป Edit method request ใน resource ที่ต้องการ จากนั้นติ๊กที่ช่อง API Key required.

เนื้อหาส่วนที่ผ่านมาจะเป็นการเตรียม resource ในส่วนของ API Gateway ที่จำเป็นต้องใช้งานทั้งหมดแล้ว ส่วนต่อจากนี้จะเป็นการสร้าง API ในการสร้าง API Key ที่จะเอาไปใช้งานร่วมกับตัว frontend ของเรา

Setting up AWS EC2 instance

เราจะใช้งาน EC2 เป็น server สำหรับการ run backend ของเราเช่นเคย ขนาดของ instance ที่ใช้งานเลือกเป็น size ปานกลางก็พอครับ เพราะว่าไม่ได้ใช้งานอะไรมาก และสิ่งที่ขาดไม่ได้เลยก็คือเราจำเป็นต้องมีการเพิ่ม Role ให้กับ EC2 ของเราในการใช้งาน aws-sdk สำหรับการสั่งงาน AWS API Gateway ผ่าน backend โดยเราต้องการ permission เพียงพอต่อการสร้าง API Key และควบคุม Usage plan

Setting up FastAPI backend

ทำการติดตั้ง 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

Connect to AWS with boto3

การใช้งาน aws-sdk เราจะใช้งานผ่าน library ที่ชื่อว่า boto3

*เครื่อง EC2 ที่ใช้จำเป็นต้องมี permission ที่เพียงพอต่อการใช้งาน

pip install boto3

วิธีการเรียกใช้งาน

import boto3
client = boto3.client(
    'apigateway',
    region_name = 'ap-southeast-1')

เป็นการสร้าง client สำหรับใช้งาน apigateway โดยสามารถดูข้อมูลเกียวกับ method ได้ที่ APIGateway - Boto3 1.28.84 documentation (amazonaws.com)

API Design and deployment

Design

ในการออกแบบ API ที่เราจะใช้งาน เราจะสร้างไว้ทั้งหมด 2 เส้นด้วยกันคือ

  1. ใช้สำหรับดู usage plan ที่มีให้บริการ
def get_plan():
    res = client.get_usage_plans()
    plan_name_list = []
    for i in res['items']:
        plan_name_list.append({
            "name":i['name']
        })
    return JSONResponse(content=plan_name_list, status_code=200)
response:
[{"name":"20RequestPerDay"},{"name":"30RequestPerDay"},{"name":"10RequestPerDay"}]

response ที่จะได้เป็น plan ที่เราสร้างไว้ใน usage plan ของ API Gateway

  1. สร้าง API Key ไปยัง usage plan ที่เลือก โดยจะมี condition คือ ในแต่ละ usage plan จะต้องไม่มี API Key name ซ้ำกัน (เราจะใช้ email เป็น API Key name ไปเลย)
Body:
{
  "plan_name" : "20RequestPerDay",
  "user" : "test@mail.com"
}
@app.post("/create_key")
async def create_key(create_request :create_request ):
    res = module.check_user_exist_in_plan(create_request.user,create_request.plan_name)
    if res is True:
        raise HTTPException(status_code=409, detail="Key already exist")
    else:
        response = client.create_api_key(
            name=create_request.user,
            description='for use api',
            enabled=True,
            generateDistinctId=True
        )
        api_key = response['value']
        api_id = response['id']
        try:
            module.add_key_to_plan(api_id,create_request.plan_name)
            result = {
                "value" : api_key
            }
            return JSONResponse(content=result, status_code=200)
        except Exception as e:
            client.delete_api_key(
                apiKey=api_id
            )
            result = {
                "message" : "create failed"
            }
            return JSONResponse(content=result, status_code=500)
response: 
{
  "value" : "keyxxxxxxxxxxx"
}

Response จะคือค่า API-key ที่สร้างสำเร็จกลับมา และเราสามารถนำ Key นั้นไปใช้งานต่อได้เลย

และตัวอย่างนี้เราทำเป็น POC ง่ายๆให้เพื่อนๆได้ไปลองศึกษากันต่อ ซึ่งยังมีอีกหลายอย่างเลยที่ทางเราเองคิดว่าต้องทำเพิ่ม ไม่ว่าจะเป็น การลงทะเบียนก่อนใช้งาน, การลบ key ที่ไม่ได้ใช้งาน, การแสดงจำนวนครั้งที่เหลือ

Deploy

เช่นกันกับตัวอย่างก่อนหน้า เราจะใช้ screen ในการแยก session และ deploy FastAPI โดยใช้

uvicorn app:app --host 0.0.0.0

เพื่อรัน server ใน port 8000

Testing call API with API Key

ในการเรียกใช้งาน API Key ผ่าน AWS API Gateway เราจะนำ key ที่ได้มาส่งผ่าน header ชื่อว่า x-api-key

{
  "x-api-key": "7wuOmY7Osz721X1bQUkAP2aGUFxxxxxxxx"
}

ในการเรียกทุกครั้ง API Gateway ก็จะทำการอ่าน Key และส่งยังไป Backend ที่เราได้ config ไว้ในตอนแรก

ทิ้งท้ายบทความสำหรับ OpenAI with ratelimit

OpenAI with ratelimit frontend

OpenAI with ratelimit backend

Github Frontend

Github Backend

FAQ Facebook Group

Aa

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