[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

Startup JAPAN 2025 に出展いたしました

Startup JAPAN 2025 に出展いたしました

こんにちは! 2025年5月8日(木)-5月9日(金)に東京ビッグサイトで開催された Startup JAPAN 2025 に出展いたしましたので、簡単にレポートいたします😊 開催概要 出展概要 今回は当社が開発するアバター動画生成AI「MotionVox™」を中心に出展させていただきました! 展示会について簡単にふりかえってみたいとおもいます 当社ブース 当社ブースはこんなかんじです。 今回は、ブースというか、このイーゼルのような雰囲気の木枠にポスターをくっつけるというスタイルでの展示方式でした。 こういう方式ははじめてなので斬新でした。おそらくこの方式で相当なコストダウンを図れておりスタートアップにはうれしいですね。セットアップも数分で終わりました。 会場 今回の会場はビッグサイトの南ホールでした。南ホールは、ビッグサイト入口からすぐそこなので駅から会場までたいして歩かず、疲れずに行くことができアクセスがとても良いです。 ホールは広めですが、ところせましと400社の出展会社がひしめきあっておりスタートアップの勢いのある会場となっており

By Qualiteg ビジネス開発本部 | マーケティング部
GPUサービスで「Segmentation Fault 」に出会ったら~分析から解決までの実践アプローチ~

GPUサービスで「Segmentation Fault 」に出会ったら~分析から解決までの実践アプローチ~

こんにちは! 今日は仮想環境+GPUなサービスにおける「Segmentation Fault」について、分析と対処法について書いてみたいと思います。 Segmentation Faultの本質と特徴 Segmentation Faultは、プログラムが保護されたメモリ領域にアクセスしようとした際にOSが発生させる例外です。 今回は複数のGPUサービス(つまりGPUを使うプロセス)が動作していて、そのうちの1つを再起動したときに発生しました。 毎回発生するわけではありません。むしろ数百回の起動に1回程度ですが、1回でも発生すると絶望的な結果につながります。というのも、1つのGPUサービスの停止が SPOF となってサービス全体に影響が発生します。かつ、1回でも「Segmentation Fault」が発生してしまうと、その原因となったプロセスが二度と起動しなくなる、というやっかいな現象でした。 このように「普段は正常に動作しているのに突然動かなくなる」というのがデバッグを非常に難しくします。 とくにGPU+仮想化の組み合わせで従来のC++アプリよりも発生確率がぐっとあがる印象

By Qualiteg プロダクト開発部
シェルスクリプトからcondaコマンドを活用したいとき

シェルスクリプトからcondaコマンドを活用したいとき

こんにちは! 今日はみんな大好きcondaコマンドについてです。 condaコマンドで仮想環境に入って、何らかの処理をして、戻ってくる ようなシェルスクリプト、バッチタスクをやるときのTipsです。 AI開発において、Anacondaとその中核であるcondaパッケージマネージャーはとっても重宝します。 しかし、シェルスクリプトから自動的にcondaを利用しようとすると、意外なハードルがあります。 本記事では、シェルスクリプトからcondaコマンドを正しく呼び出す方法について解説します。 condaと非対話モードの課題 AnacondaがインストールされているLinux環境において、condaコマンドは通常、.bashrcや.bash_profileなどの設定ファイルによって初期化されます。 なんとなくシェルをつかっていると、このcondaコマンドの初期化を忘れてしまいますが、これらの設定は多くの場合シェルの「対話モード」でのみ有効になるように設計されています。 ゆえにシェルスクリプトのような非対話モードでは、condaコマンドが正しく機能してくれません 例えば、.b

By Qualiteg プロダクト開発部
Node.jsで大容量ファイルを扱う:AIモデルのような大きなデータ保存はストリーム処理使いましょう

Node.jsで大容量ファイルを扱う:AIモデルのような大きなデータ保存はストリーム処理使いましょう

こんにちは!今日はAIシステムのフロントサーバーとしてもよく使用するNode.jsについてのお話です。 AIモデルの普及に伴い、大容量のデータファイルを扱う機会が急増しています。LLMなどのモデルファイルやトレーニングデータセットは数GB、場合によっては数十、数百GBにも達することがあります。 一方、Node.jsはWebアプリケーションのフロントサーバーとして広く採用されており、データマネジメントやPythonで書かれたAIバックエンドとの橋渡し役としてもかなりお役立ちな存在です。 本記事では、Node.js v20LTSで5GB程度のファイルを処理しようとして遭遇した問題と、その解決方法について解説します。 Node.jsのバッファサイズ制限の変遷 Node.jsのバッファサイズ制限は、バージョンによって大きく変化してきました Node.jsバージョン サポート終了日 バッファサイズ上限 備考 Node.js 0.12.x 2016年12月31日 ~1GB 初期のバッファサイズ制限(smalloc.kMaxLength使用) Node.js 4.

By Qualiteg プロダクト開発部