요기약(4)
원래 huggingface에서 API 요청을 해서 데이터를 받아오는 식으로 모델과 연결을 수행하려했지만, 모델의 JSON응답을 받아오는 과정에서 계속 문제가 발생하여 ngrok을 이용해서 모델과 연결하는 방식을 선택하였다
Ngrok
로컬 개발 환경에서 인터넷을 통해 웹 애플리케이션에 안전하게 접근할 수 있도록 해주는 도구
연결 방법
- 로컬 서버 실행: 모델을 로컬 환경에서 실행하고 이를 웹 서버로 감쌉니다 (예: Flask나 FastAPI로 REST API 구현).
- ngrok으로 터널링: ngrok을 사용해 로컬 서버에 대한 임시 공용 URL을 생성합니다.
- 외부 시스템에서 요청: 생성된 ngrok URL을 통해 외부 시스템이 로컬 서버에 요청을 보냅니다
원래 함수 -> 서버가 먼저 시작되고 ngrok 생성 안되는 문제 계속 발생
import asyncio
from pyngrok import ngrok
import uvicorn
import nest_asyncio
from fastapi import FastAPI
app = FastAPI()
# 예시 엔드포인트
@app.get("/")
def read_root():
return {"message": "Hello World"}
async def start_ngrok():
# ngrok 터널 시작
public_url = ngrok.connect(8000)
print(f" * Public URL: {public_url}")
return public_url
async def start_server():
# ngrok을 먼저 시작하고 그 다음에 서버 시작
await start_ngrok()
# nest_asyncio 적용 (코랩 환경에서 필요)
nest_asyncio.apply()
# 서버 시작
uvicorn.run(app, host="0.0.0.0", port=8000)
if __name__ == "__main__":
asyncio.run(start_server()) # 비동기로 서버 시작
따라서, @app.on_event("startup") 안에다가 넣음
서버가 시작될 때 자동으로 ngrok 연결이 설정되고 public URL이 출력됨. ngrok 연결이 서버 시작과 동시에 이루어지도록 보장
@app.on_event("startup")
async def startup_event():
global chatbot
# 샘플 데이터 생성 및 저장
sample_df = create_sample_data()
data_dir = "/content/sample_data"
os.makedirs(data_dir, exist_ok=True)
temp_file = f"{data_dir}/sick.xlsx"
sample_df.to_excel(temp_file, index=False)
# 챗봇 초기화
chatbot = SimplifiedMedicalChatbot(temp_file)
# ngrok 연결 설정
public_url = ngrok.connect(8000)
print(f" * Public URL: {public_url}")
C:\Users\mini0\Anaconda3\envs\gamza\lib\asyncio\runners.py", line 33, in run [1] [0] raise RuntimeError( [1] [0] RuntimeError: asyncio.run() cannot be called from a running event loop [1] [0] python utils/model_connection.py exited with code 1
에러발생!! 이미 실행 중인 이벤트 루프 내에서 asyncio.run()을 호출하려고 했기 때문에 발생
- start_server() 함수를 수정하여 uvicorn.run()을 직접 호출하는 대신 비동기 설정을 사용:
async def start_server():
config = uvicorn.Config(app, host="0.0.0.0", port=8000)
server = uvicorn.Server(config)
await server.server()
2. 메인 스크립트에서 asyncio.run() 대신 이벤트 루프를 직접 생성하고 관리:
if __name__ == "__main__":
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
try:
loop.run_until_complete(start_server())
finally:
loop.close()
이렇게 해도 에러가 해결 안되서 비동기 -> 동기로 바꿈 && 로그 출력에 flush 사용
print(f" * Public URL: {public_url}", flush=True)
이후에
이렇게 에러가 나서 보니,,,,,
형식이 모델에서 요구하는 것과 다름
모델에서는 bornYear이 str형식인데 여기서는 숫자였었음~!
드디어ㅠ 완성했다!!