[ChatStream] Web サーバー(ASGI server) の起動

[ChatStream] Web サーバー(ASGI server) の起動

こんにちは! (株)Qualiteg プロダクト開発部 です!

本稿では、 ChatStream 搭載した Webサーバーの起動方法について説明いたします!

uvicorn(内部起動)

ChatStreamは FastAPI/Starlette に対応しているため、 ASGI サーバーで動作させることができます。

uvicorn をコード内で定義するには以下のように実装します

def start_server():
    uvicorn.run(app, host='localhost', port=9999)


def main():
    start_server()


if __name__ == "__main__":
    main()

ソースコード全体

import torch
import uvicorn
from fastapi import FastAPI, Request
from fastersession import FasterSessionMiddleware, MemoryStore
from transformers import AutoTokenizer, AutoModelForCausalLM

from chatstream import ChatStream, ChatPromptTogetherRedPajamaINCITEChat as ChatPrompt

model_path = "togethercomputer/RedPajama-INCITE-Chat-3B-v1"
device = "cuda"  # "cuda" / "cpu"

tokenizer = AutoTokenizer.from_pretrained(model_path)
model = AutoModelForCausalLM.from_pretrained(model_path, torch_dtype=torch.float16)
model.to(device)

chat_stream = ChatStream(
    num_of_concurrent_executions=2,
    max_queue_size=5,
    model=model,
    tokenizer=tokenizer,
    device=device,
    chat_prompt_clazz=ChatPrompt,
)

app = FastAPI()

app.add_middleware(FasterSessionMiddleware,
                   secret_key="your-session-secret-key",  # Key for cookie signature
                   store=MemoryStore(),  # Store for session saving
                   http_only=True,  # True: Cookie cannot be accessed from client-side scripts such as JavaScript
                   secure=True,  # False: For local development env. True: For production. Requires Https
                   )


@app.post("/chat_stream")
async def stream_api(request: Request):
    # handling FastAPI/Starlette's Request
    response = await chat_stream.handle_chat_stream_request(request)
    return response


@app.on_event("startup")
async def startup():
    # start request queueing system
    await chat_stream.start_queue_worker()


def start_server():
    uvicorn.run(app, host='localhost', port=9999)


def main():
    start_server()


if __name__ == "__main__":
    main()

uvicorn(外部起動)

次に uvicorn 外部起動 のパターンについてみていきましょう。

./example にある example_server_redpajama_simple.py をサーバーとして起動する場合

uvicorn example.web_server_redpajama_simple.py:app --host 0.0.0.0 --port 3000

のようになります。こちらのほうがサーバーとアプリの分離ができていて、より本番に近いアプローチとなります。

uvicornの起動オプション

https://www.uvicorn.org/settings/

ソースコード

example_server_redpajama_simple.py

import torch
import uvicorn
from fastapi import FastAPI, Request
from fastersession import FasterSessionMiddleware, MemoryStore
from transformers import AutoTokenizer, AutoModelForCausalLM

from chatstream import ChatStream, ChatPromptTogetherRedPajamaINCITEChat as ChatPrompt

model_path = "togethercomputer/RedPajama-INCITE-Chat-3B-v1"
device = "cuda"  # "cuda" / "cpu"

tokenizer = AutoTokenizer.from_pretrained(model_path)
model = AutoModelForCausalLM.from_pretrained(model_path, torch_dtype=torch.float16)
model.to(device)

chat_stream = ChatStream(
    num_of_concurrent_executions=2,
    max_queue_size=5,
    model=model,
    tokenizer=tokenizer,
    device=device,
    chat_prompt_clazz=ChatPrompt,
)

app = FastAPI()

app.add_middleware(FasterSessionMiddleware,
                   secret_key="your-session-secret-key",  # Key for cookie signature
                   store=MemoryStore(),  # Store for session saving
                   http_only=True,  # True: Cookie cannot be accessed from client-side scripts such as JavaScript
                   secure=True,  # False: For local development env. True: For production. Requires Https
                   )


@app.post("/chat_stream")
async def stream_api(request: Request):
    # handling FastAPI/Starlette's Request
    response = await chat_stream.handle_chat_stream_request(request)
    return response


@app.on_event("startup")
async def startup():
    # start request queueing system
    await chat_stream.start_queue_worker()

gunicorn

次は gunicorn を使用する方法についてです。こちらは、本番のAPIサーバーとして、もっとも一般的なアプローチとなります。ここで起動した gunicorn を APIサーバーとして Nginx などの Webサーバーをリバースプロキシとして組み合わせることで、本番システムとして稼働させることができます。

./example にある example_server_redpajama_simple.py をサーバーとして起動する場合

gunicorn example.web_server_redpajama_simple.py:app --workers 4 --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:3000

(注意:Windows 環境では動作しません)

ソースコード

example_server_redpajama_simple.py

import torch

from fastapi import FastAPI, Request
from fastersession import FasterSessionMiddleware, MemoryStore
from transformers import AutoTokenizer, AutoModelForCausalLM

from chatstream import ChatStream, ChatPromptTogetherRedPajamaINCITEChat as ChatPrompt

model_path = "togethercomputer/RedPajama-INCITE-Chat-3B-v1"
device = "cuda"  # "cuda" / "cpu"

tokenizer = AutoTokenizer.from_pretrained(model_path)
model = AutoModelForCausalLM.from_pretrained(model_path, torch_dtype=torch.float16)
model.to(device)

chat_stream = ChatStream(
    num_of_concurrent_executions=2,
    max_queue_size=5,
    model=model,
    tokenizer=tokenizer,
    device=device,
    chat_prompt_clazz=ChatPrompt,
)

app = FastAPI()

app.add_middleware(FasterSessionMiddleware,
                   secret_key="your-session-secret-key",  # Key for cookie signature
                   store=MemoryStore(),  # Store for session saving
                   http_only=True,  # True: Cookie cannot be accessed from client-side scripts such as JavaScript
                   secure=True,  # False: For local development env. True: For production. Requires Https
                   )


@app.post("/chat_stream")
async def stream_api(request: Request):
    # handling FastAPI/Starlette's Request
    response = await chat_stream.handle_chat_stream_request(request)
    return response


@app.on_event("startup")
async def startup():
    # start request queueing system
    await chat_stream.start_queue_worker()

いかがでしたでしょうか。ChatStreamが FastAPI/Starlette ベースで実装されているので本番に向けては標準的なアプローチでサーバー構築することが可能です。

ただし、商用環境を考慮しますと、通常、1つの ChatStream APIサーバーだけで運用することは稀で、1つの ChatStream API サーバーを ChatStreamノードと呼び、複数のChatStreamノードでリージョンごとのクラスターを作ります。Qualiteg では、このようなスケールアウト型の負荷対策をさせるシステム構成を推奨しております。

Read more

「Blackwell」は 1 つではなかった。NVIDIA の Compute Capability 番号のわかりにくさを整理する

「Blackwell」は 1 つではなかった。NVIDIA の Compute Capability 番号のわかりにくさを整理する

こんにちは! NVIDIA の GPU を扱っていると、sm_120 や sm_100 といった番号を見かけます。Compute Capability と呼ばれる番号です。 この番号、製品の世代名と対応しているように見えて、実はずれています。 きっかけは、2026年9月23日に公開された TensorRT-LLM の v1.3.0rc28 でした。リリースノートに「SM107」という記述があります。次世代の Rubin に対応した、という文脈です。 ここで引っかかります。Blackwell の GeForce は sm_120 です。次の世代の Rubin が、なぜ 107 という小さい番号なのでしょうか。 調べてみると、引っかかりの原因は Rubin ではありませんでした。

By Qualiteg プロダクト開発部