Hub documentation

첫 번째 Docker Space: T5를 활용한 텍스트 생성

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

첫 번째 Docker Space: T5를 활용한 텍스트 생성

다음 섹션에서는 Docker Space를 만들고, 설정하며, 코드를 배포하는 기본 사항을 학습합니다. FastAPI를 서버로 사용하여 일부 입력 텍스트를 주면 텍스트를 생성할 수 있는 google/flan-t5-small 모델을 데모하기 위해 Docker 기반 Text Generation Space를 생성합니다.

호스팅된 이 문서의 완성된 버전을 여기에서 찾을 수 있습니다.

새로운 Docker Space 만들기

새로운 Space를 생성하고 SDK로 Docker를 선택하는 것부터 시작하겠습니다.

Hugging Face Spaces는 Git 저장소이므로 커밋을 푸시하여 Space를 점진적으로(그리고 협업하여) 작업할 수 있습니다. 계속하기 전에 파일을 생성하고 편집하는 방법에 대해 알아보려면 Getting Started with Repositories 가이드를 참고하세요. UI를 사용하여 작업하는 것을 선호한다면 브라우저에서 직접 작업을 수행할 수도 있습니다.

README.md 파일의 YAML 블록에서 sdk 속성을 docker으로 설정하여 새로운 Space를 생성할 때 Docker를 SDK로 선택하면 Docker Space가 초기화됩니다.

sdk: docker

README.md 파일의 YAML 블록에서 app_port 속성을 설정하여 Space의 기본 애플리케이션 포트를 변경할 수 있습니다. 기본 포트는 7860입니다.

app_port: 7860

의존성을 추가

Text Generation Space의 경우, 텍스트 생성 모델인 Flan T5를 소개하는 FastAPI 앱을 구축합니다. 모델 추론을 위해 모델을 사용하려면 🤗 Transformers pipeline을 사용합니다. 먼저 몇 가지 의존성을 설치해야 합니다. 이를 위해 저장소에 requirements.txt 파일을 생성하고, 아래 의존성을 추가합니다:

fastapi==0.74.*
requests==2.27.*
sentencepiece==0.1.*
torch==1.11.*
transformers==4.*
uvicorn[standard]==0.17.*

이 의존성들은 나중에 생성할 Dockerfile에 설치됩니다.

앱 만들기

가짜 FastAPI 앱을 만들어 엔드포인트가 정상적으로 작동하는지 확인하면서 프로세스를 시작해 보겠습니다. 첫 단계는 앱 파일을 만드는 것이며, 이 경우 파일 이름을 main.py로 지정합니다.

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
    return {"Hello": "World!"}

Dockerfile 생성

Docker Space의 핵심 단계는 Dockerfile을 작성하는 것입니다. Dockerfile에 대한 자세한 내용은 여기에서 확인할 수 있습니다. 이 튜토리얼에서는 FastAPI를 사용하지만, Dockerfile은 사용자에게 높은 유연성을 제공하여 새로운 세대의 ML 데모를 구축할 수 있게 합니다. 이제 우리 애플리케이션을 위한 Dockerfile을 작성해 보겠습니다.

# read the doc: https://huggingface.co/docs/hub/spaces-sdks-docker
# you will also find guides on how best to write your Dockerfile

FROM python:3.9

# The two following lines are requirements for the Dev Mode to be functional
# Learn more about the Dev Mode at https://huggingface.co/dev-mode-explorers
RUN useradd -m -u 1000 user
WORKDIR /app

COPY --chown=user ./requirements.txt requirements.txt
RUN pip install --no-cache-dir --upgrade -r requirements.txt

COPY --chown=user . /app
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"]

변경 사항이 저장되면 Space가 다시 빌드되며 몇 초 후 데모가 실행됩니다! 여기는 이 시점의 예시 결과입니다.

로컬에서 테스트

고급 사용자 팁(건너뛰어도 됩니다): 로컬에서 개발 중이라면, docker build와 docker run를 실행하여 로컬에서 디버깅하기에 좋은 시점입니다. 하지만 변경 사항을 Hub에 push하고 그 모습을 확인하는 것이 더 쉽습니다!

docker build -t fastapi .
docker run  -it -p 7860:7860 fastapi

Secrets가 있는 경우 docker buildx를 사용하여 시크릿을 빌드 인수로 전달할 수 있습니다

export SECRET_EXAMPLE="my_secret_value"
docker buildx build --secret id=SECRET_EXAMPLE,env=SECRET_EXAMPLE -t fastapi .

docker run를 실행하고 시크릿을 환경 변수로 전달합니다

export SECRET_EXAMPLE="my_secret_value"
docker run -it -p 7860:7860 -e SECRET_EXAMPLE=$SECRET_EXAMPLE fastapi

애플리케이션에 ML 추가하기

앞서 언급했듯이, 텍스트 생성을 위해 Flan T5 모델을 사용하는 것이 핵심 아이디어입니다. 입력 필드를 위해 HTML과 CSS를 추가해야 하므로, index.html, style.css, script.js 파일이 포함된 static이라는 이름의 디렉터리를 만들어 보겠습니다. 이 시점에서 파일 구조는 다음과 같아야 합니다:

/static
/static/index.html
/static/script.js
/static/style.css
Dockerfile
main.py
README.md
requirements.txt

이 작업을 수행하기 위한 모든 단계를 살펴보겠습니다. CSS와 HTML의 일부 세부 사항은 생략합니다. 전체 코드는 DockerTemplates/fastapi_t5 Space의 Files and versions 탭에서 확인할 수 있습니다.

  1. FastAPI 엔드포인트를 작성하여 추론을 수행합니다

transformers의 pipeline을 사용하여 google/flan-t5-small 모델을 로드합니다. 입력을 받아 추론 호출의 결과를 출력하는 infer_t5라는 엔드포인트를 설정합니다.

from transformers import pipeline

pipe_flan = pipeline("text2text-generation", model="google/flan-t5-small")

@app.get("/infer_t5")
def t5(input):
    output = pipe_flan(input)
    return {"output": output[0]["generated_text"]}
  1. 페이지 코드를 포함하는 간단한 양식을 index.html에 작성합니다.
<main>
  <section id="text-gen">
    <h2>Text generation using Flan T5</h2>
    <p>
      Model:
      <a
        href="https://huggingface.co/google/flan-t5-small"
        rel="noreferrer"
        target="_blank"
        >google/flan-t5-small
      </a>
    </p>
    <form class="text-gen-form">
      <label for="text-gen-input">Text prompt</label>
      <input
        id="text-gen-input"
        type="text"
        value="German: There are many ducks"
      />
      <button id="text-gen-submit">Submit</button>
      <p class="text-gen-output"></p>
    </form>
  </section>
</main>
  1. main.py 파일에서 정적 파일을 마운트하고 루트 경로에서 html 파일을 표시합니다
app.mount("/", StaticFiles(directory="static", html=True), name="static")

@app.get("/")
def index() -> FileResponse:
    return FileResponse(path="/app/static/index.html", media_type="text/html")
  1. script.js 파일에서 요청을 처리하도록 만듭니다.
const textGenForm = document.querySelector(".text-gen-form");

const translateText = async (text) => {
  const inferResponse = await fetch(`infer_t5?input=${text}`);
  const inferJson = await inferResponse.json();

  return inferJson.output;
};

textGenForm.addEventListener("submit", async (event) => {
  event.preventDefault();

  const textGenInput = document.getElementById("text-gen-input");
  const textGenParagraph = document.querySelector(".text-gen-output");

  textGenParagraph.textContent = await translateText(textGenInput.value);
});
  1. 적절한 디렉토리에 권한 부여

Permissions Section에서 논의했듯이, 컨테이너는 사용자 ID 1000으로 실행됩니다. 즉, Space에서 권한 관련 문제가 발생할 수 있습니다. 예를 들어, transformers는 HF_HOME 경로 아래에 모델을 다운로드하고 캐시합니다. 이를 해결하는 가장 쉬운 방법은 올바른 권한을 가진 사용자를 생성하고, 해당 사용자로 컨테이너 애플리케이션을 실행하는 것입니다. Dockerfile에 다음 줄을 추가하여 이를 수행할 수 있습니다.

# Switch to the "user" user
USER user

# Set home to the user's home directory
ENV HOME=/home/user \
	PATH=/home/user/.local/bin:$PATH

최종 Dockerfile은 다음과 같아야 합니다:


# read the doc: https://huggingface.co/docs/hub/spaces-sdks-docker
# you will also find guides on how best to write your Dockerfile

FROM python:3.9

# The two following lines are requirements for the Dev Mode to be functional
# Learn more about the Dev Mode at https://huggingface.co/dev-mode-explorers
RUN useradd -m -u 1000 user
WORKDIR /app

COPY --chown=user ./requirements.txt requirements.txt
RUN pip install --no-cache-dir --upgrade -r requirements.txt

COPY --chown=user . /app

USER user

ENV HOME=/home/user \
	PATH=/home/user/.local/bin:$PATH

CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"]

성공! 이제 앱이 정상적으로 작동해야 합니다. 최종 결과를 확인하려면 DockerTemplates/fastapi_t5를 살펴보세요.

정말 흥미로운 여정이었죠! Docker Spaces는 다양한 자유도를 제공하므로 FastAPI 사용에 국한되지 않습니다. Go Endpoint부터 Shiny App까지, 한계는 달입니다! 공식 예제를 확인해 보세요. 필요 시 Space를 GPU로 업그레이드할 수도 있습니다 😃

디버깅

Space를 디버깅하려면 Build 및 Container 로그를 확인하세요. Open Logs 버튼을 클릭하여 모달을 엽니다.

모든 과정이 순조롭게 진행되었다면 Build 탭에서 Pushing Image와 Scheduling Space를 확인할 수 있습니다

Container 탭에서 애플리케이션 상태를 확인할 수 있으며, 이 경우 Uvicorn running on http://0.0.0.0:7860입니다.

또한 Space에서 Dev Mode를 활성화할 수 있습니다. Dev Mode를 사용하면 실행 중인 Space에 VSCode 또는 SSH를 통해 연결할 수 있습니다. 자세한 내용은 https://huggingface.co/dev-mode-explorers에서 확인하세요.

자세히 보기

Update on GitHub