Xinference의 내부 구조#

개요#

Xinference는 당사가 설계한 actor 프로그래밍 프레임워크 Xoscar 를 핵심 구성 요소로 사용하여 머신, 장치 및 모델 추론 프로세스를 관리합니다. 각 actor는 모델 추론의 기본 단위이며, 다양한 추론 백엔드를 actor에 통합하여 여러 추론 엔진과 하드웨어를 지원할 수 있습니다. 이러한 actor는 리소스 풀 기능을 갖춘 actor 풀에서 호스팅 및 스케줄링되며, actor는 비동기 및 논블로킹 방식으로 설계되었습니다.

actor

supervisor와 worker는 모두 actor 인스턴스입니다. 먼저 각 서버에서 리소스 풀 역할을 하는 actor 풀을 생성해야 합니다. 각 actor는 하나의 CPU 코어 또는 하나의 GPU 장치를 사용할 수 있습니다. 각 서버는 고유한 주소(IP 주소 또는 호스트 이름)를 가지므로, 서로 다른 컴퓨팅 노드에 있는 actor는 이러한 주소를 통해 서로 통신할 수 있습니다. 자세한 내용은 `Actor`_를 참조하십시오.

RESTful API#

RESTful API는 FastAPI 를 사용하여 구현되었으며, 구체적인 코드는 api/restful_api.py 에 있습니다.

self._router.add_api_route("/status", self.get_status, methods=["GET"])

이것은 API의 예시로, API ``/status``는 함수 ``get_status``에 대응됩니다. api/restful_api.py 에서 RESTful API와 해당 백엔드 함수 간의 관계를 추가할 수 있습니다.

명령줄#

명령줄은 Click 으로 구현되었으며, 구체적인 코드는 deploy/cmdline.py 에 있습니다. 명령줄을 통해 사용자는 터미널에서 직접 Xinference와 상호작용할 수 있습니다.

입구 지점#

우리가 구현한 명령줄을 예로 들면:

  • xinference: 모델 관리를 위한 명령을 제공하며, 모델 등록/등록 취소, 등록/실행 중인 모든 모델 목록 보기, 특정 모델 시작 또는 종료 기능을 포함합니다. 또한 배포된 모델을 테스트하거나 상호작용하기 위한 언어 생성 및 채팅 등의 대화형 명령도 제공합니다.

  • xinference-local: 로컬 Xinference 서비스를 시작합니다.

  • xinference-supervisor: supervisor 프로세스를 시작하여 분산 환경에서 worker 액터를 관리하고 모니터링합니다.

  • xinference-worker: 워커 프로세스를 시작하여 사용 가능한 컴퓨팅 리소스를 활용해 supervisor가 할당한 작업을 실행합니다.

각 명령어에는 ``option``과 ``flag``가 포함되어 있어, 로그 수준, 호스트 주소, 포트 번호 및 기타 관련 설정을 지정하는 등 동작을 사용자 정의할 수 있습니다.

Python 프로젝트는 setup.cfg 또는 `setup.py`에서 명령줄 콘솔 엔트리 포인트를 정의합니다.

console_scripts =
    xinference = xinference.deploy.cmdline:cli
    xinference-local = xinference.deploy.cmdline:local
    xinference-supervisor = xinference.deploy.cmdline:supervisor
    xinference-worker = xinference.deploy.cmdline:worker

명령줄 xinferencexinference.deploy.cmdline:cli 의 코드를 참조할 수 있습니다.

Click#

우리는 Click을 사용하여 특정 명령줄을 구현합니다.

@click.option(
      "--host",
      "-H",
      default=XINFERENCE_DEFAULT_DISTRIBUTED_HOST,
      type=str,
      help="Specify the host address for the supervisor.",
  )
  @click.option(
      "--port",
      "-p",
      default=XINFERENCE_DEFAULT_ENDPOINT_PORT,
      type=int,
      help="Specify the port number for the Xinference web ui and service.",
  )

예를 들어, xinference-local 명령어를 사용하면 호스트 주소와 포트를 정의할 수 있습니다.

Actor#

Xinference는 Xoscar 을 기반으로 하며, Xoscar는 컴퓨팅 리소스와 Python 프로세스를 관리하고 확장 가능한 동시성 프로그래밍을 지원하는 액터 프레임워크입니다. 아래 의사 코드는 Worker Actor의 작동 방식을 보여주며, 실제 Worker Actor는 이보다 훨씬 복잡합니다.

import xoscar as xo

class WorkerActor(xo.Actor):
    def __init__(self, *args, **kwargs):
        ...
    async def launch_model(self, model_id, n_gpu, ...):
        # launch an inference engine, use specific model class to load model checkpoints
        ...
    async def list_models(self):
        # list models on this actor
        ...
    async def terminate_model(self, model_id):
        # terminate the model
        ...
    async def __post_create__(self):
        # called after the actor instance is created
        ...
    async def __pre_destroy__(self):
        # called before the actor instance is destroyed
        ...

``WorkerActor``를 예시로 Xinference를 구축하는 방법을 설명하겠습니다. 각 액터 클래스는 ``xoscar.Actor``를 상속받는 표준 Python 클래스입니다. 이 클래스의 인스턴스는 액터 풀 내의 특정 액터입니다.

  • Actor의 행동 정의하기: 각 actor는 특정 작업을 완료하기 위해 특정 동작이나 행위를 정의해야 합니다. 예를 들어, 모델 추론 WorkerActor``는 모델을 시작하고(``launch_model), 해당 actor의 모델을 나열하며(list_models), 모델을 종료해야(terminate_model) 합니다. 주목할 만한 두 가지 특별한 메서드가 있습니다. ``__post_create__``는 actor가 생성되기 전에 호출되어 필요한 초기화를 수행합니다. 반면 ``__pre_destroy__``는 actor가 소멸된 후에 호출되어 정리 작업을 실행합니다.

  • Actor 참조 및 메서드 호출: Actor를 생성하면 참조 변수가 생성되어 다른 Actor가 이를 참조할 수 있습니다. Actor는 IP 주소로도 참조할 수 있습니다. WorkerActor``가 생성되고 참조 변수가 ``worker_ref``라면, ``worker_ref.launch_model()``을 호출하여 해당 Actor 클래스의 ``launch_model 메서드를 호출할 수 있습니다. Actor 내의 메서드가 원래 전통적인 블로킹 방식의 메서드라 하더라도, 참조 변수를 사용하여 이 메서드를 호출하면 비동기 메서드로 변환됩니다.

  • 추론 엔진: Actor는 프로세스를 관리할 수 있으며, 추론 엔진 역시 일종의 프로세스입니다. ``WorkerActor``의 시작 모델 부분에서 사용자의 필요에 따라 다양한 추론 엔진을 초기화할 수 있습니다. 따라서 Xinference는 여러 추론 엔진을 지원하며, 향후 새로운 추론 엔진에도 쉽게 적응할 수 있습니다.

Xoscar 문서 에서 더 많은 Actor 사용 사례를 참조하세요.

비동기 프로그래밍#

Xinference와 Xoscar는 비동기 프로그래밍 라이브러리 ``asyncio``에 크게 의존합니다. 비동기 프로그래밍은 논블로킹 프로그래밍 패러다임입니다. 전통적인 블로킹 방식의 함수 호출과 달리, 비동기 프로그래밍에서는 요청이나 함수 호출이 백그라운드에서 실행되며, 실행 결과는 미래의 특정 시점에 반환됩니다. 비동기 프로그래밍의 장점은 여러 가지 다양한 활동이나 작업을 동시에 병행하여 수행할 수 있다는 점입니다.

만약 Python의 ``asyncio``에 익숙하지 않다면, 더 많은 튜토리얼을 참고하여 도움을 받을 수 있습니다:

model#

Xinference는 대형 언어 모델(LLM), 이미지 모델, 오디오 모델, 임베딩 모델 등 다양한 유형의 모델을 지원합니다. 모든 모델은 model/ 폴더에서 구현됩니다.

LLM#

model/llm/ 를 예로 들면, 주로 LLM을 관리하고 시작하며, 대규모 언어 모델의 로딩, 구성 및 실행을 포함합니다.

우리는 GGML, PyTorch, vLLM 등 다양한 추론 백엔드를 지원합니다. 생성된 콘텐츠는 OpenAI 형식과 호환되며, 예를 들어 스트리밍 출력(stream)을 지원하고, 대화 모델은 chat completion 형식으로 반환됩니다. 따라서 모델 출력 후 많은 적응 작업이 필요합니다. 이러한 작업은 어렵지 않지만 시간이 다소 소요됩니다. 이 부분의 코드를 작성할 때는 OpenAI API 문서 및 각 추론 백엔드 문서를 참고하여 필요한 적응을 수행하십시오.

JSON#

model/llm/llm_family.json 에서, 우리는 JSON 파일을 사용하여 새로 등장하는 오픈소스 모델의 메타데이터를 관리합니다. 새 모델을 추가하기 위해 새로운 코드를 작성할 필요 없이, 기존 JSON 파일에 새로운 메타데이터만 추가하면 됩니다.

{
    "model_name": "llama-2-chat",
    "model_ability": ["chat"],
    "model_specs": [
        {
            "model_format": "ggmlv3",
            "model_size_in_billions": 70,
            "quantization": ["q8_0", ...],
            "model_id": "TheBloke/Llama-2-70B-Chat-GGML",
        },
        ...
    ],
    "prompt_style": {
        "style_name": "LLAMA2",
        "system_prompt": "<s>[INST] <<SYS>>\nYou are a helpful AI assistant.\n<</SYS>>\n\n",
        "roles": ["[INST]", "[/INST]"],
        "stop_token_ids": [2],
        "stop": ["</s>"]
    }
}

다음은 Llama-2 채팅 모델을 정의하는 예시입니다. `model_specs`는 모델 정보를 정의하며, 하나의 모델 시리즈는 일반적으로 다양한 크기, 양자화 방법 및 파일 형식을 가지기 때문입니다. 예를 들어, `model_format`은 `pytorch`(Hugging Face Transformers 또는 vLLM을 백엔드로 사용), `ggmlv3`(llama.cpp 관련 텐서 라이브러리) 또는 `gptq`(훈련 후 양자화 프레임워크)일 수 있습니다. `model_id`는 모델 허브의 리포지토리를 정의하며, Xinference는 모델 허브에서 체크포인트 파일을 다운로드합니다. 또한, 서로 다른 명령어 조정 프로세스로 인해 모델 시리즈마다 프롬프트 스타일이 다릅니다. JSON 파일의 `prompt_style`은 특정 모델의 프롬프트 형식을 지정합니다. 예를 들어, `system_prompt`와 `roles`는 모델의 명령어와 특성을 지정하는 데 사용됩니다.

Code Guide#

주요 코드는 `xinference/ <xorbitsai/inference>`_에 있습니다.

  • api/`restful_api.py <xorbitsai/inference>`_는 RESTful API를 설정하고 실행하는 핵심 부분입니다. 일부 또는 모든 포트에 사용자 인증이 필요하기 때문에, 인증 서비스(구체적인 코드는 `oauth2/ <xorbitsai/inference>`_에 위치)를 통합하고 있습니다.

  • client/:Xinference의 클라이언트입니다.

    • oscar/ 는 Actor 클라이언트를 정의하며, 이는 Xinference에서 모델과 상호작용하기 위한 클라이언트 인터페이스입니다.

    • restful/ Xinference 서비스와 상호작용하는 RESTful 클라이언트를 구현합니다.

  • core/: Xinference의 핵심 부분입니다.

    • metrics.pyresource.py 는 모델 처리량, 지연 시간, CPU 및 GPU 사용률, 메모리 사용률 등 지표와 노드 리소스 상태를 수집하고 보고하기 위한 도구 세트를 정의합니다.

    • image_interface.pychat_interface.py <https://github.com/xorbitsai/inference/tree/main/xinference/core/chat_interface.py>`_는 각각 이미지 및 채팅 모델에 대해 `Gradio 인터페이스를 구현합니다. 이러한 인터페이스는 사용자가 웹 인터페이스를 통해 모델과 상호작용할 수 있도록 하며, 예를 들어 이미지를 생성하거나 채팅을 할 수 있습니다. 코드는 Gradio 패키지를 사용하여 사용자 인터페이스를 구축하고, RESTful API를 통해 백엔드 모델과 통신합니다.

    • worker.pysupervisor.py 는 각각 worker actor와 supervisor actor의 로직을 정의합니다. worker actor는 특정 모델 연산 작업을 실행하며, supervisor actor는 Worker 노드의 수명 주기와 작업 스케줄링을 관리하고 시스템 상태를 모니터링합니다.

    • `status_guard.py <xorbitsai/inference>`_는 모델의 상태(예: 생성, 업데이트, 종료 등)를 추적하는 상태 모니터를 구현합니다. 이를 통해 모델의 UID를 기반으로 모델 인스턴스의 상태 정보를 조회할 수 있습니다.

    • cache_tracker.py 는 캐시 상태와 모델 버전 정보를 기록하고 관리하는 캐시 추적기를 정의합니다. 캐시 위치와 모델 버전의 상태를 기록하고, 모델 이름을 기준으로 모델 버전 정보를 조회할 수 있습니다.

    • event.py 는 다양한 런타임 모델의 정보, 경고 및 오류와 같은 이벤트를 수집하고 보고하는 이벤트 수집기를 정의합니다. model.py 는 모델과 직접 상호작용하는 핵심 구성 요소인 모델 액터를 정의합니다. 모델 액터는 모델 추론 요청을 실행하고, 입력 및 출력 데이터 스트림을 처리하며, 다양한 모델 작업을 지원합니다. 이 두 부분 모두 Xoscar 를 사용하여 동시 및 분산 실행을 구현합니다.

  • deploy/:Xinference 프레임워크와 상호작용하기 위한 CLI(Command Line Interface)를 제공하며, 사용자가 명령줄을 통해 작업을 수행할 수 있도록 합니다. 자세한 내용은 `Command Line`_을 참조하십시오.

  • locale/:다국어 로컬라이제이션을 지원합니다. JSON 번역 파일을 추가하고 업데이트하기만 하면 더 많은 언어를 지원하고 사용자 경험을 개선할 수 있습니다.

  • model/ : 모델 설명, 생성 및 캐싱을 위한 프레임워크를 제공합니다. 자세한 내용은 Model 을 참조하십시오.

  • web/ui/:프론트엔드(사용자 인터페이스)의 js 코드입니다.