최근 프로젝트에서 텍스트/이미지 임베딩을 .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 자체는 아직 완성도가 높은 수준은 아니지만, 필요한 기능을 확장할 수 있어서 오히려 테스트 해보기 좋았다.