Amazon Bedrock 및 OpenSearch를 사용하여 멀티 모달 래그 앱을 구축하십시오
대본
스크린 샷이있는 고객 지원 티켓, 다이어그램이 포함 된 기술 문서 및 레거시 PDF의 산 (모두 귀중한 정보가 포함되어 있지만 효율적으로 쿼리 할 수 없습니다.
“더 나은 방법이 있어야한다”고 생각했다. 그때 나는 멀티 모달 검색-섭취 세대 (RAG)의 세계로 머리를 불고 있습니다.
복합 계시
많은 개발자들과 마찬가지로, 나는 텍스트에 충분히 잘 작동하는 기본 래그 시스템을 실험했습니다. 그러나 우리의 실제 데이터는 단순한 텍스트가 아닙니다. 고객이 설명과 함께 오류의 스크린 샷을 보낼 때 또는 의료 고객이 환자 노트와 방사선 이미지를 교차 참조해야 할 때 텍스트 전용 헝겊이 부족합니다.
계시는 우리가 임베딩을 생성 할 수 있다는 것을 깨달았을 때 왔습니다. 다른 유형 데이터 (텍스트, 이미지 및 잠재적으로 오디오)의 데이터와 함께 사용합니다. 멀티 모달 헝겊 시스템을 AWS로 구축하여 배운 것을 공유하겠습니다.
이를 가능하게 한 AWS 서비스
사용자 정의 솔루션으로 몇 차례의 허위가 시작된 후 놀랍게 잘 작동하는 조합에 착륙했습니다.
- 아마존 기반암 임베딩과 LLM 모두
- 아마존 오브 펜스 검색 벡터 데이터베이스로
- AWS Lambda 및 API 게이트웨이 배포를 위해
왜이 스택인가? 솔직히, 나는 나 자신의 임베딩 모델을 유지하려고 시도했으며 GPU 프로비저닝 및 버전 충돌의 악몽이었습니다. Bedrock의 완전히 관리되는 접근 방식은 인프라 대신 응용 프로그램 논리에 집중할 수 있음을 의미했습니다.
내가 그것을 지은 방법 : 아키텍처
다음은 궁극적으로 우리를 위해 일한 접근법입니다.
1. 데이터 수집 파이프 라인
첫 번째 과제는 다양한 데이터를 임베딩으로 변환하는 것이 었습니다. 텍스트의 경우 솔루션은 간단했습니다.
import boto3
import json
bedrock = boto3.client(service_name="bedrock-runtime")
def get_text_embedding(text):
response = bedrock.invoke_model(
body=json.dumps({"inputText": text}),
modelId="amazon.titan-embed-text-v1",
accept="application/json",
contentType="application/json"
)
return json.loads(response.get('body').read())['embedding']
그러나 이미지의 경우로드 블록을 쳤다. 여러 접근 방식을 실험 한 후 Sagemaker에 클립 모델을 배치하여 이미지를 동일한 임베딩 공간으로 변환했습니다. 이것은 제대로되기가 까다 롭습니다. 치수를 신중하게 관리해야했습니다.
2. 벡터 검색을위한 OpenSearch 설정
가장 까다로운 부분은 OpenSearch를 올바르게 구성하는 것입니다. 잘못된 치수로 몇 차례 실패한 시도 후이 매핑은 마침내 작동했습니다.
PUT /rag-index
{
"mappings": {
"properties": {
"embedding": {
"type": "knn_vector",
"dimension": 1536 # Titan Embeddings dimension
},
"text": {"type": "text"},
"image_embedding": {
"type": "knn_vector",
"dimension": 512 # CLIP embedding dimension
}
}
}
}
주의 한 단어 : 차원 값이 임베딩 모델과 정확히 일치하는지 확인하십시오. 그렇지 않으면 내가했던 것처럼 암호 오류를 디버깅하는 데 몇 시간을 소비합니다!
3. 프로젝트를 구한 검색 논리
솔루션의 가장 우아한 부분은 검색 기능이었습니다. 처음에 나는 복잡한 하이브리드 접근법을 시도했지만 더 나은 일이 더 단순한 것으로 끝났습니다.
def retrieve_documents(query_text, query_image=None):
query_embedding = get_text_embedding(query_text)
knn_query = {
"size": 5,
"query": {
"knn": {
"embedding": {
"vector": query_embedding,
"k": 5
}
}
}
}
results = opensearch.search(body=knn_query, index="rag-index")
return results['hits']['hits']
진짜 마법은 이것을 기반암의 Claude와 결합 할 때 발생했습니다.
def generate_answer(query, context):
prompt = f"""Human: Answer this query: {query} using the context:
{context}
A:"""
response = bedrock.invoke_model(
body=json.dumps({"prompt": prompt}),
modelId="anthropic.claude-v2"
)
return json.loads(response.get('body').read())['completion']
실제 영향과 교훈
우리가 이것을 생산에 배치했을 때, 결과는 즉각적이었습니다. 이전에 “이 오류를 설명 할 수없고 여기 스크린 샷이 있습니다”티켓으로 어려움을 겪었던 고객 지원 팀은 이제 비슷한 과거 문제를 즉시 검색 할 수 있습니다.
어려운 수업 :
- 비용 관리가 중요합니다. 생성 비용을 포함 시키면 빠르게 추가 될 수 있습니다. API 통화를 70%줄인 캐싱 레이어를 구현했습니다.
- 텍스트로 시작한 다음 이미지를 추가하십시오. 멀티 모달 문제를 한 번에 해결하려고 시도하지 마십시오. 먼저 텍스트를 완벽하게 작동시킵니다.
- 대기 시간이 중요합니다. 우리는 처음에 모든 것을 Lambda에 넣었지만 대규모 임베딩 작업을 위해 Elasticache에 캐시 된 결과가있는 전용 EC2 인스턴스로 옮겼습니다.
멀티 모달 헝겊 시스템의 미래
이 접근 방식을 비디오 컨텐츠로 확장하게되어 가장 기쁩니다. 우리는 키 프레임 추출과 관련 비디오 세그먼트를 검색하는 데 도움이되는 임베딩을 생성하는 실험을 실험하고 있습니다.
또한 오디오를 멀티 모달 믹스에 가져 오기 위해 음성 전사를 추가하려고합니다. 문서 및 스크린 샷과 함께 고객 통화를 통해 검색 할 수 있다고 상상해보십시오.
직접 시도하십시오
연결이 끊어진 데이터 소스와 비슷한 도전에 직면해도 멀티 모달 래그를 실험하는 것이 좋습니다. 아마도 텍스트와 몇 가지 테스트 이미지로 작게 시작하십시오. AWS 스택은 반복을 비교적 고통스럽게 만듭니다.
Post Comment