Backend

[Backend] FastAPI+Hugging Face

dong_seok 2024. 5. 11. 20:12
1. Hugging Face 
2. Hugging Face와 FastAPI 통신
3. FastAPI와 Next.js 통신 

 

오늘은 졸업 프로젝트에서 사용한 FastAPI를 사용하여 Hugging Face에 등록된 모델의 API를 통해 데이터를 요청하고, 이를 Next.js에서 요청하여 응답하는 일련의 과정에 대해 알아보도록 하겠습니다.

 

1. Hugging Face 

트랜스포머 기반의 다양한 모델들과 학습 스크립트를 구현해놓은 일종의 모듈입니다. 기존의 트랜스포머를 학습시킨다고 하면 딥러닝 프레임워크를 선택하고, 그에 맞게 구현을 해야했습니다. 하지만 허깅페이스는 그런 함수들이 이미 정의 되어있기 때문에, 간단하게 모델을 불러서 쓸 수 있습니다. 또한 가장 좋은 점은 다른 누군가가 이미 학습한 모델을 가져다 쓸 수도 있다는 것입니다. 

2. Hugging Face와 FastAPI 통신

먼저 Hugging Face에 있는 다양한 모델중 하나를 가져와서 FastAPI에서 출력해보도록 하겠습니다. 단순히 Hugging Face model을 보는 건 로그인을 하지 않아도 되지만 model을 API로 가져오기 위해서는 로그인을 하고 토큰을 발급 받아야합니다.

 

1) 모델 API

 

로그인을 하고 위의 사진과 같이 원하는 모델을 선택해줍니다.

 

 

그리고 Deploy에서 "Inference API (serverless)를 클릭해줍니다.

 

그러면 위와 같은 화면이 뜨고 Python, JavaScript, cURL 중 원하는 언어를 선택해서 모델의 API 코드를 얻을 수 있습니다. 하지만 그전에 Token이 없다면 반드시 발급 받아야 모델을 사용할 수 있기때문에 New access token 을 클릭해서 Token을 발급받으 후 코드를 가져다가 사용하면 됩니다.

 

2) FastAPI 에서 model 가져다가 사용하기

pycharm에서 venv 가상환경을 실행한뒤 requests 패키지만 설치하고 output을 출력해 보았습니다. 그랬더니 "{'error': 'Model deepset/roberta-base-squad2 is currently loading', 'estimated_time': 20.0}" 라는 에러가 출력되고 실행결과가 제대로 나오지 않았습니다. 위의 에러는 모델이 처음 로드 될때 시간이 소요돼서 걸리는 에러인것 같았습니다. 시간이 좀 지나고 다시 실행해보니

 

 

정상적인 결과를 얻을 수 있었습니다. model이 성공적으로 작동하는걸 확인해보았으니 이번엔 FastAPI를 활용해 모델의 출력 결과를 화면에 띄워주도록 하겠습니다. 

from fastapi import FastAPI

app = FastAPI()

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

 

먼저 venv에 FastAPI 를 설치한 후 서버가 정상적으로 작동되는지 확인해보았습니다.

 

실행 명령어

uvicorn main:app --reload

 

서버가 정상적으로 작동되는걸 확인했으니 모델을 가져와서 FastAPI를 통해 통신해보겠습니다.

 

from fastapi import FastAPI

app = FastAPI()

@app.get("/translate")
def read_root(originText: str):
    data=query(
        {
            "inputs": {
                "question": "What's my name?",
                "context": f"{originText}",
            }
        })
    return {"translatedText": data}

 

GET 요청을 처리하기 위한 엔드포인트를 "/translate"로 작성하였습니다. 그리고 뒤에 쿼리 파라미터 이름으로 originText를 주고 파라미터 값을 받아서 "context" 에 넣어주도록 했습니다. 통신이 잘 이루어지는지 확인해보도록하겠습니다.

 

위에서 모델 Api를 테스트할때 사용했던 "My name is Clara and I live in Berkeley" 을 context로 주었고 결과도 위와 똑같이 나온 모습을 볼 수 있습니다(%20은 공백을 의미)

 

3. FastAPI와 Next.js 통신 

FastAPI와 Hugging Face 사이에 통신이 잘 이루어지는 걸 확인했으니 이제 Next.js에서 FastApi로 데이터를 요청해서 모델 결과를 응답받는 것까지 해보겠습니다.

 

  handleTranslate = (originText: string) => {
    const url = "http://localhost:8000/translate?originText=" + originText;
    fetch(url, {
      method: "get",
    })
      .then((res) => res.json())
      .then((json) => {
        console.log(json);
        this.setState({ translatedText: json.translateText });
      });
  };

Next.js 에서 FastAPI에 request 하는 코드만 가져온 것입니다. 정상적으로 response하는지 확인하기 위해 console 에 찍어서 확인해보았습니다.

 

잘 작동할줄 알았는데 오류가 새빨갛게 나와서 당황했습니다.... 찾아보니 CORS (Cross-Origin Resource Sharing) 정책으로 인해 발생한 오류였습니다. 이 정책은 웹 애플리케이션이 다른 도메인 또는 포트에서 리소스를 요청할 때 브라우저가 이를 차단하는 보안 기능입니다. 이에 당황스러웠지만, 다행히도 이 문제는 일반적으로 FastAPI의 CORS 설정을 통해 쉽게 해결할 수 있습니다. 서버에서 CORS 헤더를 응답에 포함시켜 클라이언트로부터의 요청을 허용할 수 있으며, 대부분의 백엔드 프레임워크에서는 CORS를 구성할 수 있는 미들웨어 또는 설정 옵션을 제공합니다. 이를 통해 요청을 보내는 도메인이나 포트를 명시적으로 허용할 수 있습니다. 이제 원활한 통신을 위해 CORS 설정을 적용하여 문제를 해결해 보도록 하겠습니다.

 

from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

origins = [
    # "http://192.168.0.13:3000", # url을 등록해도 되고
    "*" # private 영역에서 사용한다면 *로 모든 접근을 허용할 수 있다.
]

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True, # cookie 포함 여부를 설정한다. 기본은 False
    allow_methods=["*"],    # 허용할 method를 설정할 수 있으며, 기본값은 'GET'이다.
    allow_headers=["*"],	# 허용할 http header 목록을 설정할 수 있으며 Content-Type, Accept, Accept-Language, Content-Language은 항상 허용된다.
)

 

FastAPI에서 CORS를 제어할때 사용하는 CORSMiddleware라는 모듈을 사용하였습니다. 다시 Next.js 에서 요청을 보내보았더니

 

 

이번에는 콘솔에 올바르게 찍힌 모습을 확인할 수 있었습니다. 이제 json 형태의 데이터중 원하는 값을 가져다가 사용하면 됩니다! 오늘은 FastAPI로 데이터를 요청하고, Hugging Face 모델 API를 활용하여 다시 Next.js에 응답하는 과정을 배워보았습니다. 이러한 과정을 통해 전체적인 데이터 흐름과 서버-클라이언트 간의 통신 방식을 이해하는 데 큰 도움이 되었습니다.

 

 

참고자료

https://ongamedev.tistory.com/479

https://huggingface.co/docs/api-inference/detailed_parameters

https://jaeyoon-95.tistory.com/222

 

 

 

 

 

'Backend' 카테고리의 다른 글

[Backend] FastAPI  (0) 2024.06.18