LLM가지고 뚝딱거리다보면, 종종 만날 수 있는 오류 메시지.
LLM에 대한 이해도가 낮은터라, 왜 오류인지 이해하기 어렵다.
내 경우 아래의 코드 때문에 발생했다. (아마 나랑 다들 비슷할듯)
pipeline("question-answering", "MY MODEL")
digging
쪼끔 복잡한 내용을 보면,
pipeline 함수는 첫번째 파라미터에 연결된 클래스를 호출하여 사용한다.
pipeline 설명을 보면 나오지만, 아래처럼 연결시킨다고 한다(길어서 일부 생략)
- `"question-answering"`: will return a [`QuestionAnsweringPipeline`].
- `"summarization"`: will return a [`SummarizationPipeline`].
- `"table-question-answering"`: will return a [`TableQuestionAnsweringPipeline`].
- `"text2text-generation"`: will return a [`Text2TextGenerationPipeline`].
- `"text-classification"` (alias `"sentiment-analysis"` available): will return a [`TextClassificationPipeline`].
그렇다. question-answering은 결국 QuestionAnsweringPipeline 클래스의 인스턴스라는 것.
QuestionAsnweringPipeline을 보면 __call__이 불리는 쪽 같고, super를 호출하고..
super는 ChunkPipeline이고, 따라가보 preprocess, forward, postprocess가 거의 순차적으로 호출되겠구나.
다시 원 클래스로 돌아와서 preprocess를 보고..
안되겠다 싶어서 start_logits를 찾아보니 output에 있긴 한데, model 에서 가져오는거네?
그럼 PreTrainedModel이나 TFPreTrainedModel 중에 하나이고.. 실제 인스턴트는 상속 받아서 다를 수 있으니까..
아 더 보기 싫다.
우회
hugginface questionanswering으로 검색
https://huggingface.co/docs/transformers/main/en/tasks/question_answering
그래 친절한 공식 가이드에서 start_logits를 찾아보자.
answer_start_index = outputs.start_logits.argmax()
answer_end_index = outputs.end_logits.argmax()
이런 코드들이 보이는데, 오호라 접근 방식이 dictionary가 아니고 실제 outputs에 멤버로 start_logits가 있다는 것을 알 수 있다.
그리고 위에 보면 outputs은 model이 반환하고 model은 AutoModelForQuestionAnswering이다.
from_pretrained 를 보면, 매우 많은 QA 모델이 추상화 되어 있는 것을 볼 수 있고, 아직도 반환 값을 안 알려준다.. xxx
아무 모델이나 하나 찜해서 들어가보자
나는 한번 말이라도 들어본 deberta를 선택
그래 QuestionAnsweringModelOutput 니가 반환 값이구나
그런데.. 이걸보고 뭘 어쩌라는건가 싶을 수도 있는데, 이미 지나온 과정에 답이 있었다.
추정
- QuestionAnswering task를 수행하려면 QuestionAnswering Model이어야 함
- 해당 모델은 위에서 봤던 추상화된 모델들임 (DEBERTA, gpt2, gptj, roberta 등등)
- 내가 선택한 모델이 위에 해당하는 것이 아님
- 내가 선택한 모델은 QuestionAnswering 용 모델이 아님
결론
바보. ㅠㅠ
QuestionAnswer task를 수행할 수 있는 전용 모델이 있고 내가 선택한 모델은 해당하지 않는 모델임
나는 어떤 Question-Answering이란,
pipeline내부에서 prompt/completion 등을
이쁘게 정리해주는 것으로
설명도 안읽고 그럴거라 믿었다.