Spaces:
				
			
			
	
			
			
		Paused
		
	
	
	
			
			
	
	
	
	
		
		μ΄λ»κ² μ¬μ©μ μ μ νμ΄νλΌμΈμ μμ±νλμ? [[how-to-create-a-custom-pipeline]]
μ΄ κ°μ΄λμμλ μ¬μ©μ μ μ νμ΄νλΌμΈμ μ΄λ»κ² μμ±νκ³ νλΈμ 곡μ νκ±°λ π€ Transformers λΌμ΄λΈλ¬λ¦¬μ μΆκ°νλ λ°©λ²μ μ΄ν΄λ³΄κ² μ΅λλ€.
λ¨Όμ  νμ΄νλΌμΈμ΄ μμ©ν  μ μλ μμ μ
λ ₯μ κ²°μ ν΄μΌ ν©λλ€.
λ¬Έμμ΄, μμ λ°μ΄νΈ, λμ
λ리 λλ κ°μ₯ μνλ μ
λ ₯μΌ κ°λ₯μ±μ΄ λμ κ²μ΄λ©΄ 무μμ΄λ  κ°λ₯ν©λλ€.
μ΄ μ
λ ₯μ κ°λ₯ν ν μμν Python νμμΌλ‘ μ μ§ν΄μΌ (JSONμ ν΅ν΄ λ€λ₯Έ μΈμ΄μλ) νΈνμ±μ΄ μ’μμ§λλ€.
μ΄κ²μ΄ μ μ²λ¦¬(preprocess) νμ΄νλΌμΈμ μ
λ ₯(inputs)μ΄ λ  κ²μ
λλ€.
κ·Έλ° λ€μ outputsλ₯Ό μ μνμΈμ.
inputsμ κ°μ μ μ±
μ λ°λ₯΄κ³ , κ°λ¨ν μλ‘ μ’μ΅λλ€.
μ΄κ²μ΄ νμ²λ¦¬(postprocess) λ©μλμ μΆλ ₯μ΄ λ  κ²μ
λλ€.
λ¨Όμ  4κ°μ λ©μλ(preprocess, _forward, postprocess λ° _sanitize_parameters)λ₯Ό ꡬννκΈ° μν΄ κΈ°λ³Έ ν΄λμ€ Pipelineμ μμνμ¬ μμν©λλ€.
from transformers import Pipeline
class MyPipeline(Pipeline):
    def _sanitize_parameters(self, **kwargs):
        preprocess_kwargs = {}
        if "maybe_arg" in kwargs:
            preprocess_kwargs["maybe_arg"] = kwargs["maybe_arg"]
        return preprocess_kwargs, {}, {}
    def preprocess(self, inputs, maybe_arg=2):
        model_input = Tensor(inputs["input_ids"])
        return {"model_input": model_input}
    def _forward(self, model_inputs):
        # model_inputs == {"model_input": model_input}
        outputs = self.model(**model_inputs)
        # Maybe {"logits": Tensor(...)}
        return outputs
    def postprocess(self, model_outputs):
        best_class = model_outputs["logits"].softmax(-1)
        return best_class
μ΄ λΆν ꡬ쑰λ CPU/GPUμ λν λΉκ΅μ  μνν μ§μμ μ 곡νλ λμμ, λ€λ₯Έ μ€λ λμμ CPUμ λν μ¬μ /μ¬ν μ²λ¦¬λ₯Ό μνν μ μκ² μ§μνλ κ²μ λλ€.
preprocessλ μλ μ μλ μ
λ ₯μ κ°μ Έμ λͺ¨λΈμ 곡κΈν  μ μλ νμμΌλ‘ λ³νν©λλ€.
λ λ§μ μ λ³΄λ₯Ό ν¬ν¨ν  μ μμΌλ©° μΌλ°μ μΌλ‘ Dict ννμ
λλ€.
_forwardλ ꡬν μΈλΆ μ¬νμ΄λ©° μ§μ  νΈμΆν  μ μμ΅λλ€. 
forwardλ μμ μ₯μΉμμ λͺ¨λ  κ²μ΄ μλνλμ§ νμΈνκΈ° μν μμ μ₯μΉκ° ν¬ν¨λμ΄ μμ΄ μ νΈλλ νΈμΆ λ©μλμ
λλ€.
μ€μ  λͺ¨λΈκ³Ό κ΄λ ¨λ κ²μ _forward λ©μλμ μνλ©°, λλ¨Έμ§λ μ μ²λ¦¬/νμ²λ¦¬ κ³Όμ μ μμ΅λλ€.
postprocess λ©μλλ _forwardμ μΆλ ₯μ κ°μ Έμ μ΄μ μ κ²°μ ν μ΅μ’
 μΆλ ₯ νμμΌλ‘ λ³νν©λλ€.
_sanitize_parametersλ μ΄κΈ°ν μκ°μ pipeline(...., maybe_arg=4)μ΄λ νΈμΆ μκ°μ pipe = pipeline(...); output = pipe(...., maybe_arg=4)κ³Ό κ°μ΄, μ¬μ©μκ° μνλ κ²½μ° μΈμ λ μ§ λ§€κ°λ³μλ₯Ό μ λ¬ν  μ μλλ‘ νμ©ν©λλ€.
_sanitize_parametersμ λ°ν κ°μ preprocess, _forward, postprocessμ μ§μ  μ λ¬λλ 3κ°μ kwargs λμ
λ리μ
λλ€.
νΈμΆμκ° μΆκ° λ§€κ°λ³μλ‘ νΈμΆνμ§ μμλ€λ©΄ μ무κ²λ μ±μ°μ§ λ§μμμ€.
μ΄λ κ² νλ©΄ νμ λ "μμ°μ€λ¬μ΄" ν¨μ μ μμ κΈ°λ³Έ μΈμλ₯Ό μ μ§ν  μ μμ΅λλ€.
λΆλ₯ μμ
μμ top_k λ§€κ°λ³μκ° λνμ μΈ μμ
λλ€.
>>> pipe = pipeline("my-new-task")
>>> pipe("This is a test")
[{"label": "1-star", "score": 0.8}, {"label": "2-star", "score": 0.1}, {"label": "3-star", "score": 0.05}
{"label": "4-star", "score": 0.025}, {"label": "5-star", "score": 0.025}]
>>> pipe("This is a test", top_k=2)
[{"label": "1-star", "score": 0.8}, {"label": "2-star", "score": 0.1}]
μ΄λ₯Ό λ¬μ±νκΈ° μν΄ μ°λ¦¬λ postprocess λ©μλλ₯Ό κΈ°λ³Έ λ§€κ°λ³μμΈ 5λ‘ μ
λ°μ΄νΈνκ³  _sanitize_parametersλ₯Ό μμ νμ¬ μ΄ μ λ§€κ°λ³μλ₯Ό νμ©ν©λλ€.
def postprocess(self, model_outputs, top_k=5):
    best_class = model_outputs["logits"].softmax(-1)
    # top_kλ₯Ό μ²λ¦¬νλ λ‘μ§ μΆκ°
    return best_class
def _sanitize_parameters(self, **kwargs):
    preprocess_kwargs = {}
    if "maybe_arg" in kwargs:
        preprocess_kwargs["maybe_arg"] = kwargs["maybe_arg"]
    postprocess_kwargs = {}
    if "top_k" in kwargs:
        postprocess_kwargs["top_k"] = kwargs["top_k"]
    return preprocess_kwargs, {}, postprocess_kwargs
μ /μΆλ ₯μ κ°λ₯ν ν κ°λ¨νκ³ μμ ν JSON μ§λ ¬ν κ°λ₯ν νμμΌλ‘ μ μ§νλ €κ³ λ Έλ ₯νμμμ€. μ΄λ κ² νλ©΄ μ¬μ©μκ° μλ‘μ΄ μ’ λ₯μ κ°μ²΄λ₯Ό μ΄ν΄νμ§ μκ³ λ νμ΄νλΌμΈμ μ½κ² μ¬μ©ν μ μμ΅λλ€. λν μ¬μ© μ©μ΄μ±μ μν΄ μ¬λ¬ κ°μ§ μ νμ μΈμ(μ€λμ€ νμΌμ νμΌ μ΄λ¦, URL λλ μμν λ°μ΄νΈμΌ μ μμ)λ₯Ό μ§μνλ κ²μ΄ λΉκ΅μ  μΌλ°μ μ λλ€.
μ§μλλ μμ λͺ©λ‘μ μΆκ°νκΈ° [[adding-it-to-the-list-of-supported-tasks]]
new-taskλ₯Ό μ§μλλ μμ
 λͺ©λ‘μ λ±λ‘νλ €λ©΄ PIPELINE_REGISTRYμ μΆκ°ν΄μΌ ν©λλ€:
from transformers.pipelines import PIPELINE_REGISTRY
PIPELINE_REGISTRY.register_pipeline(
    "new-task",
    pipeline_class=MyPipeline,
    pt_model=AutoModelForSequenceClassification,
)
μνλ κ²½μ° κΈ°λ³Έ λͺ¨λΈμ μ§μ ν μ μμΌλ©°, μ΄ κ²½μ° νΉμ  κ°μ (λΆκΈ° μ΄λ¦ λλ μ»€λ° ν΄μμΌ μ μμ, μ¬κΈ°μλ "abcdef")κ³Ό νμ μ ν¨κ» κ°μ ΈμμΌ ν©λλ€:
PIPELINE_REGISTRY.register_pipeline(
    "new-task",
    pipeline_class=MyPipeline,
    pt_model=AutoModelForSequenceClassification,
    default={"pt": ("user/awesome_model", "abcdef")},
    type="text",  # νμ¬ μ§μ μ ν: text, audio, image, multimodal
)
Hubμ νμ΄νλΌμΈ 곡μ νκΈ° [[share-your-pipeline-on-the-hub]]
Hubμ μ¬μ©μ μ μ νμ΄νλΌμΈμ 곡μ νλ €λ©΄ Pipeline νμ ν΄λμ€μ μ¬μ©μ μ μ μ½λλ₯Ό Python νμΌμ μ μ₯νκΈ°λ§ νλ©΄ λ©λλ€.
μλ₯Ό λ€μ΄, λ€μκ³Ό κ°μ΄ λ¬Έμ₯ μ λΆλ₯λ₯Ό μν μ¬μ©μ μ μ νμ΄νλΌμΈμ μ¬μ©νλ€κ³  κ°μ ν΄ 보겠μ΅λλ€:
import numpy as np
from transformers import Pipeline
def softmax(outputs):
    maxes = np.max(outputs, axis=-1, keepdims=True)
    shifted_exp = np.exp(outputs - maxes)
    return shifted_exp / shifted_exp.sum(axis=-1, keepdims=True)
class PairClassificationPipeline(Pipeline):
    def _sanitize_parameters(self, **kwargs):
        preprocess_kwargs = {}
        if "second_text" in kwargs:
            preprocess_kwargs["second_text"] = kwargs["second_text"]
        return preprocess_kwargs, {}, {}
    def preprocess(self, text, second_text=None):
        return self.tokenizer(text, text_pair=second_text, return_tensors=self.framework)
    def _forward(self, model_inputs):
        return self.model(**model_inputs)
    def postprocess(self, model_outputs):
        logits = model_outputs.logits[0].numpy()
        probabilities = softmax(logits)
        best_class = np.argmax(probabilities)
        label = self.model.config.id2label[best_class]
        score = probabilities[best_class].item()
        logits = logits.tolist()
        return {"label": label, "score": score, "logits": logits}
ꡬνμ νλ μμν¬μ ꡬμ λ°μ§ μμΌλ©°, PyTorchμ TensorFlow λͺ¨λΈμ λν΄ μλν©λλ€.
μ΄λ₯Ό pair_classification.pyλΌλ νμΌμ μ μ₯ν κ²½μ°, λ€μκ³Ό κ°μ΄ κ°μ Έμ€κ³  λ±λ‘ν  μ μμ΅λλ€:
from pair_classification import PairClassificationPipeline
from transformers.pipelines import PIPELINE_REGISTRY
from transformers import AutoModelForSequenceClassification, TFAutoModelForSequenceClassification
PIPELINE_REGISTRY.register_pipeline(
    "pair-classification",
    pipeline_class=PairClassificationPipeline,
    pt_model=AutoModelForSequenceClassification,
    tf_model=TFAutoModelForSequenceClassification,
)
μ΄ μμ
μ΄ μλ£λλ©΄ μ¬μ νλ ¨λ λͺ¨λΈκ³Ό ν¨κ» μ¬μ©ν  μ μμ΅λλ€.
μλ₯Ό λ€μ΄, sgugger/finetuned-bert-mrpcμ MRPC λ°μ΄ν° μΈνΈμμ λ―ΈμΈ μ‘°μ λμ΄ λ¬Έμ₯ μμ ν¨λ¬νλ μ΄μ¦μΈμ§ μλμ§λ₯Ό λΆλ₯ν©λλ€.
from transformers import pipeline
classifier = pipeline("pair-classification", model="sgugger/finetuned-bert-mrpc")
κ·Έλ° λ€μ Repositoryμ save_pretrained λ©μλλ₯Ό μ¬μ©νμ¬ νλΈμ 곡μ ν  μ μμ΅λλ€:
from huggingface_hub import Repository
repo = Repository("test-dynamic-pipeline", clone_from="{your_username}/test-dynamic-pipeline")
classifier.save_pretrained("test-dynamic-pipeline")
repo.push_to_hub()
μ΄λ κ² νλ©΄ "test-dynamic-pipeline" ν΄λ λ΄μ PairClassificationPipelineμ μ μν νμΌμ΄ 볡μ¬λλ©°, νμ΄νλΌμΈμ λͺ¨λΈκ³Ό ν ν¬λμ΄μ λ μ μ₯ν ν, {your_username}/test-dynamic-pipeline μ μ₯μμ μλ λͺ¨λ  κ²μ νΈμν©λλ€.
μ΄νμλ trust_remote_code=True μ΅μ
λ§ μ κ³΅νλ©΄ λꡬλ μ¬μ©ν  μ μμ΅λλ€.
from transformers import pipeline
classifier = pipeline(model="{your_username}/test-dynamic-pipeline", trust_remote_code=True)
π€ Transformersμ νμ΄νλΌμΈ μΆκ°νκΈ° [[add-the-pipeline-to-transformers]]
π€ Transformersμ μ¬μ©μ μ μ νμ΄νλΌμΈμ κΈ°μ¬νλ €λ©΄, pipelines νμ λͺ¨λμ μ¬μ©μ μ μ νμ΄νλΌμΈ μ½λμ ν¨κ» μ λͺ¨λμ μΆκ°ν λ€μ, pipelines/__init__.pyμμ μ μλ μμ
 λͺ©λ‘μ μΆκ°ν΄μΌ ν©λλ€.
κ·Έλ° λ€μ ν
μ€νΈλ₯Ό μΆκ°ν΄μΌ ν©λλ€.
tests/test_pipelines_MY_PIPELINE.pyλΌλ μ νμΌμ λ§λ€κ³  λ€λ₯Έ ν
μ€νΈμ μμ λ₯Ό ν¨κ» μμ±ν©λλ€.
run_pipeline_test ν¨μλ λ§€μ° μΌλ°μ μ΄λ©°, model_mapping λ° tf_model_mappingμμ μ μλ κ°λ₯ν λͺ¨λ  μν€ν
μ²μ μμ 무μμ λͺ¨λΈμμ μ€νλ©λλ€.
μ΄λ ν₯ν νΈνμ±μ ν
μ€νΈνλ λ° λ§€μ° μ€μνλ©°, λκ΅°κ° XXXForQuestionAnsweringμ μν μ λͺ¨λΈμ μΆκ°νλ©΄ νμ΄νλΌμΈ ν
μ€νΈκ° ν΄λΉ λͺ¨λΈμμ μ€νμ μλνλ€λ μλ―Έμ
λλ€.
λͺ¨λΈμ΄ 무μμμ΄κΈ° λλ¬Έμ μ€μ  κ°μ νμΈνλ κ²μ λΆκ°λ₯νλ―λ‘, λ¨μν νμ΄νλΌμΈ μΆλ ₯ TYPEκ³Ό μΌμΉμν€κΈ° μν λμ°λ―Έ ANYκ° μμ΅λλ€.
λν 2κ°(μ΄μμ μΌλ‘λ 4κ°)μ ν μ€νΈλ₯Ό ꡬνν΄μΌ ν©λλ€.
- test_small_model_pt: μ΄ νμ΄νλΌμΈμ λν μμ λͺ¨λΈ 1κ°λ₯Ό μ μ(κ²°κ³Όκ° μλ―Έ μμ΄λ μκ΄μμ)νκ³ νμ΄νλΌμΈ μΆλ ₯μ ν μ€νΈν©λλ€. κ²°κ³Όλ- test_small_model_tfμ λμΌν΄μΌ ν©λλ€.
- test_small_model_tf: μ΄ νμ΄νλΌμΈμ λν μμ λͺ¨λΈ 1κ°λ₯Ό μ μ(κ²°κ³Όκ° μλ―Έ μμ΄λ μκ΄μμ)νκ³ νμ΄νλΌμΈ μΆλ ₯μ ν μ€νΈν©λλ€. κ²°κ³Όλ- test_small_model_ptμ λμΌν΄μΌ ν©λλ€.
- test_large_model_pt(- μ νμ¬ν): κ²°κ³Όκ° μλ―Έ μμ κ²μΌλ‘ μμλλ μ€μ  νμ΄νλΌμΈμμ νμ΄νλΌμΈμ ν μ€νΈν©λλ€. μ΄λ¬ν ν μ€νΈλ μλκ° λ리λ―λ‘ μ΄λ₯Ό νμν΄μΌ ν©λλ€. μ¬κΈ°μμ λͺ©νλ νμ΄νλΌμΈμ 보μ¬μ£Όκ³ ν₯ν 릴리μ¦μμμ λ³νκ° μλμ§ νμΈνλ κ²μ λλ€.
- test_large_model_tf(- μ νμ¬ν): κ²°κ³Όκ° μλ―Έ μμ κ²μΌλ‘ μμλλ μ€μ  νμ΄νλΌμΈμμ νμ΄νλΌμΈμ ν μ€νΈν©λλ€. μ΄λ¬ν ν μ€νΈλ μλκ° λ리λ―λ‘ μ΄λ₯Ό νμν΄μΌ ν©λλ€. μ¬κΈ°μμ λͺ©νλ νμ΄νλΌμΈμ 보μ¬μ£Όκ³ ν₯ν 릴리μ¦μμμ λ³νκ° μλμ§ νμΈνλ κ²μ λλ€.