[.NET]Using Transformers Models : Extending TransformersSharp

최근 프로젝트에서 텍스트/이미지 임베딩을 .NET 환경에서 직접 활용할 방법을 찾아보다가, TransformersSharp라는 프로젝트를 발견했다. 이 라이브러리는 Hugging Face의 transformers Python 라이브러리를 C#에서 직접 호출할 수 있도록 wrapping한 형태다. 덕분에 별도의 Python 서버를 띄우고 REST API를 붙이지 않아도 .NET 코드 안에서 곧바로 모델을 다룰 수 있다.

TransformersSharp는 기본적으로 텍스트 기반 임베딩과 파이프라인 기능들을 제공한다. 예를 들어 SentenceTransformer를 통해 문장을 벡터화할 수 있지만 이미지를 벡터화 할 수는 없다.

그래서 직접 TransformersSharp를 fork(Link)해서 기능을 다음과 같이 확장했다.

Python Wrapper

sentence_transformers_wrapper.py에 다음 함수를 추가했다.

def load_image(url_or_path):
    if url_or_path.startswith("http://") or url_or_path.startswith("https://"):
        return Image.open(requests.get(url_or_path, stream=True).raw)
    else:
        return Image.open(url_or_path)

def encode_image(model: SentenceTransformer, image_path: str) -> Buffer:
    """
    Encode an image using the SentenceTransformer model.
    """
    image = load_image(image_path)
    return model.encode(image)

C# Wrapper

SentenceTransformer.cs에는 다음 메서드를 추가했다.

public float[] GenerateImage(string image_path)
{
    var result = TransformerEnvironment.SentenceTransformersWrapper
        .EncodeImage(transformerObject, image_path);
    return result.AsFloatReadOnlySpan().ToArray();
}

이제 텍스트와 이미지를 같은 환경에서 임베딩할 수 있다.

using Microsoft.Extensions.AI;
using TransformersSharp;

var transformer_text = SentenceTransformer.FromModel(
    "sentence-transformers/clip-ViT-B-32-multilingual-v1", 
    trustRemoteCode: true);

var transformer_image = SentenceTransformer.FromModel(
    "clip-ViT-B-32", 
    trustRemoteCode: true);

var text_embeddings = transformer_text.GenerateSentence("A dog in the snow");
var image_embeddings = transformer_image.GenerateImage(
    "https://images.unsplash.com/photo-1547494912-c69d3ad40e7f?...");

Console.WriteLine($"Text Vector: {string.Join(", ", text_embeddings.Take(10))}...");
Console.WriteLine($"Image Vector: {string.Join(", ", image_embeddings.Take(10))}...");

Python 서버 없이도 .NET 안에서 바로 모델을 다룰 수 있다는 점이 굉장히 편리한 부분이 있었다. TransformersSharp 자체는 아직 완성도가 높은 수준은 아니지만, 필요한 기능을 확장할 수 있어서 오히려 테스트 해보기 좋았다.