[AWS Cloud winter camp] 1/2 - 4일차
NLP Sneak peek
NLP Task -
기계는 사람처럼 언어를 학습하지 않아서 단계를 나누어 줘야 함
- low-level parsing : 문장분리/어근추출
- word and phrase level : 고유명사인식/형태소 분석/명사구 단위 분리/의존 구조 분석/참조 관계 분석
- sentence level : 감정 분석/기계 번역
- multi-sentence and paragraph level : 모순 관계 예측/질의 응답/대화형 챗봇/전문 요약
AI 관련 아이디어는 너무 길면 그 아이디어 빨리 쇠퇴함... 1-2달만 잡고 빨리 빨리 ... 하는 게 좋다!
word Embedding - BoW(bag of words)
벡터화 - 기계가 실제로 이해할 수 있도록 - one-hot vector -단어별 고유 벡터 지정 ->문장을 벡터의 합으로 표현 가능
-> 제약점 : 차원이 무한정으로 필요함 => 비용이 많이 든다
word2Vec - 단어의 유사도를 거리로 표현 - 특정 단어를 벡터화 하면 그 상의 거리가 가까울수록 유사, 방향이 비슷하다면 관계도 비슷하다고 봄 (벡터 - 방향과 길이가 일치하면 같은 거니까 )
PCA - 가상 선 중에 분산이 가장 높은 걸 찾는... (주 성분 분석) 사람이 보기 편하도록
처음 input에 따라 output 무조건 같지 않음. 항상 다름 (apple인풋 / apple 아웃풋...)
벡터화 시킴으로 인해서 컴퓨터가 이해할 수 있도록
이미지도 가능
문맥과의 관계... artistic한 거 이해 잘 못 함
제일 연관없는 단어도 찾을 수 있음. 같은 분류가 아닌 단어 식별
nearest neighbors
-
ES NLP
전통적인 검색 방법: 텍스트 매칭 - 실제 포함되어야지 찾을 수 있는
NLP 도입한 검색 방법 - 단어와 문장을 벡터로 인코딩해서 텍스트 임베딩
Brute force
-장점: 상위 결과를 다시 랭킹하거나 필터링함에 용이, 시간 공간이 있다면 무조건 답을 찾을 수 있음
-단점: 필드 레이어가 늘어나면... 비용 증가, 제한적임
greedy
HNSW & KNN
KNN: 최근접 이웃, 가장 가까운 쿼리-이웃-결과 등
다중 레이어로 구성
레이어마다 조금씩 이동, 찾으려는 파란색까지 도달하지 못할수도 있음
대용량 처리를 위해 약간의 정확도를 희생함
brute force 2번 하는 게 최악의 경우로 제한
brute force - 다 도는 거니까 다 돌면 너무 비효율적이니까 필터링 된 것만 돌음
HN은 전부 다 봄
6개... 1-4-3-5-7-6 이웃된... 통과된 노드
BF 이웃을 선택... 서치하고 바로 3-4 보고 끝
사용자가 원하는건 최근접한 4번 분홍색을 찾는 게 목적이었기 때문에 걔 보고 끝임
최근접 이웃 찾기
-KNN (k - 대부분의 숫자 들어가는... 우리가 정하는 후보)
-
#벡터 임베딩을 위한 파이프라인 생성
PUT _ingest/pipeline/vector_embedding_demo
{
"processors": [
{
"inference": {
"field_map": {
"document": "text_field"
},
"model_id": "sentence-transformers__all-distilroberta-v1",
"target_field": "ml.inference.document_vector",
"on_failure": [
{
"append": {
"field": "_source._ingest.inference_errors",
"value": [
{
"message": "Processor 'inference' in pipeline 'ml-inference-title-vector' failed with message '{{ _ingest.on_failure_message }}'",
"pipeline": "vector_embedding_demo",
"timestamp": "{{{ _ingest.timestamp }}}"
}
]
}
}
]
}
},
{
"set": {
"field": "document_vector",
"if": "ctx?.ml?.inference != null && ctx.ml.inference['document_vector'] != null",
"copy_from": "ml.inference.document_vector.predicted_value",
"description": "Copy the predicted_value to 'document_vector'"
}
},
{
"remove": {
"field": "ml.inference.document_vector",
"ignore_missing": true
}
}
]
}
document: 이런 텍스트 필드를 쓸거야~ (한글 리뷰 텍스트)
model_id: 이런 모델을 쓸거야
document_vector에 도큐먼트 된 필드가 저장 됨
field: 에러 나면 inference_error가 날거야~
set : ml.inference.document_vector 이름 길어서 줄이는 작업
field : 사실 이름을 바꾼 게 아니고 복사한 거고 그거 지우기 (remove)
#벡터 임베딩을 위한 인덱스 템플릿 생성
PUT _index_template/movie_ratings_vector
{
"index_patterns": [
"movie_ratings_vector"
],
"priority": 1,
"template": {
"settings": {
"number_of_shards": 1,
"number_of_replicas": 1,
"index.default_pipeline": "vector_embedding_demo"
},
"mappings": {
"properties": {
"document_vector": {
"type": "dense_vector",
"dims": 768,
"index": true,
"similarity": "dot_product"
},
"document": {
"type": "text"
}
},
"_source": {
"excludes": [
"document_vector"
]
}
}
}
}
인덱스 템플릿: 규칙
index_patterns: 이 인덱스 템플릿은 이렇게 들어갈거야~
index.default_pipeline : 디폴트 파이프라인(파이프라인의 목적은 벡터화)
mapping
document_vector : 어떤 타입인지 정확히 명시, 키워드나 텍스트-integer,double같은 벡터의 타입 dense_vector
dimension :768( , , , , ... 이 콤마가 768개 )
-> 이렇게 긴 벡터 읽기 힘듦 -> 인덱스 서치하면 보여줄 필요 없어 하는 설정이 excludes
document :text라고 명시해주는데, 안해주면 키워드랑 텍스트 둘 다 들어가서 낭비 됨
https://www.elastic.co/guide/en/machine-learning/current/ml-nlp-deploy-models.html
Deploy trained models | Machine Learning in the Elastic Stack [8.11] | Elastic
www.elastic.co
인덱스 deploy 오류 나는 경우
failed 수 뜸
index 이름 바꿔서 다시 deploy 해주면 됨
그러면 다시 됨~
# KNN Query
GET movie_ratings_vector/_search
{
"knn": [
{
"field": "document_vector",
"k": 5,
"num_candidates": 10,
"query_vector_builder": {
"text_embedding": {
"model_id": "sentence-transformers__all-distilroberta-v1",
"model_text": "갬덩"
}
}
}
]
}
# KNN + BM25 Query
GET movie_ratings_vector/_search
{
"size": 10,
"query": {
"match": {
"document": "연기"
}
},
"knn":{
"field": "document_vector",
"k": 5,
"num_candidates": 10,
"query_vector_builder": {
"text_embedding": {
"model_id": "sentence-transformers__all-distilroberta-v1",
"model_text": "좋아"
}
}
}
}
https://www.elastic.co/guide/en/elasticsearch/reference/current/knn-search.html
k-nearest neighbor (kNN) search | Elasticsearch Guide [8.11] | Elastic
Support for approximate kNN search was added in version 8.0. Before this, dense_vector fields did not support enabling index in the mapping. If you created an index prior to 8.0 containing dense_vector fields, then to support approximate kNN search the dat
www.elastic.co
"query": {
"match": {
"document": "연기" -> 연기가 있을 경우 스코어 올라감
}
},
must not으로 특정 키워드 제외시킬 수 있음
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-boosting-query.html
Boosting query | Elasticsearch Guide [8.11] | Elastic
Returns documents matching a positive query while reducing the relevance score of documents that also match a negative query. You can use the boosting query to demote certain documents without excluding them from the search results. response = client.searc
www.elastic.co
특정 키워드나 조건 부스팅 걸어서 스코어 많이 올려주는 거
뉴스 기사는 타이틀이랑 내용...
타이틀에 보통 중점 많이 두니까 knn을 비중을 두고 하는 게 잘 나옴
학술지 같은거는 내용에 좀 더 부스팅을 먹인다든지
이름 지정 안하고 올린 deployment는
한 번 더 올린 ID는 모델명_v1, v2이렇게 하면 안됨 모델인 게 아니기 때문에
명칭을 더 정확하게 dp1 dp2요렇게 해야 좋음
###삭제 쿼리 ! 주의 ! ###
POST _ml/trained_models/sentence-transformers__all-distilroberta-v1/deployment/_stop
포스트는 한 번 날리고 백단에서 하는 거임
오래 걸리면 500에러 뱉음 -> 프론트 문제고 백에서는 계속 돌고 있어서 상관없음
실행 OK
v1 dp 삭제 된 거 확인 가능
dp stopped 된 것도 noti에서 확인 가능
-
#######################
# Text Processing I #
#######################
"""
NLP에서 흔히하는 전처리는 소문자 변환, 앞뒤 필요없는 띄어쓰기를 제거하는 등의 텍스트 정규화 (text normalization)입니다.
"""
def normalize(input_string):
"""
인풋으로 받는 스트링에서 정규화된 스트링을 반환함
아래의 요건들을 충족시켜야함
* 모든 단어들은 소문자로 되어야함
* 띄어쓰기는 한칸으로 되어야함
* 앞뒤 필요없는 띄어쓰기는 제거해야함
Parameters:
input_string (string): 영어로 된 대문자, 소문자, 띄어쓰기, 문장부호, 숫자로 이루어진 string
ex - "This is an example.", " EXTRA SPACE "
Returns:
normalized_string (string): 위 요건을 충족시킨 정규회된 string
ex - 'this is an example.'
Examples:
>>> import text_processing as tp
>>> input_string1 = "This is an example."
>>> tp.normalize(input_string1)
'this is an example.'
>>> input_string2 = " EXTRA SPACE "
>>> tp.normalize(input_string2)
'extra space'
"""
# 모든 단어들은 소문자로 되어야함
normalized_string = input_string.lower()
# 띄어쓰기는 한칸으로 되어야함 + 앞뒤 필요없는 띄어쓰기는 제거해야함
normalized_string = ' '.join(normalized_string.split())
return normalized_string
def no_vowels(input_string):
"""
인풋으로 받는 스트링에서 모든 모음 (a, e, i, o, u)를 제거시킨 스트링을 반환함
Parameters:
input_string (string): 영어로 된 대문자, 소문자, 띄어쓰기, 문장부호로 이루어진 string
ex - "This is an example."
Returns:
no_vowel_string (string): 모든 모음 (a, e, i, o, u)를 제거시킨 스트링
ex - "Ths s n xmpl."
Examples:
>>> import text_processing as tp
>>> input_string1 = "This is an example."
>>> tp.normalize(input_string1)
"Ths s n xmpl."
>>> input_string2 = "We love Python!"
>>> tp.normalize(input_string2)
''W lv Pythn!'
"""
# 모음 대문자, 소문자 제거
no_vowel_string = ''.join(char for char in input_string if char not in 'aeiouAEIOU')
return no_vowel_string
-
test model
실제 벡터 dimension ? 볼 수 있음
# model_id, task type 설정
hf_model_id='distilbert-base-uncased-finetuned-sst-2-english'
tm = TransformerModel(model_id=hf_model_id, task_type='text_classification')
es_model_id = tm.elasticsearch_model_id()
# 모델 다운로드
tmp_path = "models"
Path(tmp_path).mkdir(parents=True, exist_ok=True)
model_path, config, vocab_path = tm.save(tmp_path)
# ES 탑재
ptm = PyTorchModel(es, es_model_id)
ptm.import_model(model_path=model_path, config_path=None, vocab_path=vocab_path, config=config)
실습 노트에서 model_id랑 task_type 수정해주고 실행해주면
english_model이 deploy된 걸 확인할 수 있음~
로컬에 eland깔아서 하면 금방금방 할 수 있음
POST _ml/trained_models/distilbert-base-uncased-finetuned-sst-2-english/deployment/_infer #infer 이거 탄다
{
"docs": [
{
"text_field": "The movie was awesome!"
}
]
}
###############
PUT _ingest/pipeline/sentiment_demo
{
"processors": [
{
"inference": {
"model_id": "distilbert-base-uncased-finetuned-sst-2-english", #어떤 모델 쓸지
"field_map": {
"document": "text_field" #재료, 한글로 되어 있는 리뷰 데이터 쓸거야
}
}
}
],
"on_failure": [ #실패하면 남기기, 안 남겨도 상관 없으면 제외하기
{
"set": {
"description": "Index document to 'failed-<index>'", #남길 메시지
"field": "_index",
"value": "failed-{{{_index}}}"
}
},
{
"set": {
"description": "Set error message",
"field": "ingest.failure",
"value": "{{_ingest.on_failure_message}}"
}
}
]
}
##############
POST _reindex
{
"source": {
"index": "movie_ratings_vector" #movie_ratings에서 복사해도 되는데~ vector 만들었으니까 써보려고
},
"dest": {
"index": "movie_ratings_vector_sentiment",
"pipeline": "sentiment_demo" #인덱스가 옮겨갈 때 파이프라인 타기
}
}
#############
GET movie_ratings_vector_sentiment/_search
positive 하다고 판단
negative 판단
0.5 기준에 붙어있어서 p/n 받아버리면 일단 뱉고 보는데 사람 인식하기에
이게 60퍼나 positive라고? 싶을 수 있으니 중립 꼭 적용하기
-
question answering
상여 정보/급여 정보/typical 한 문서에서 검색해서 급여 올라가는 정보가 이 문서에 있는지 ~ 같은
-
elastic은 슈퍼유저라서 delete도 되니까 유저 id 생성해서 붙기
-
vector image search
https://www.elastic.co/search-labs/blog/articles/finding-your-puppy-with-image-search
Finding your puppy with Image Search — Elastic Search Labs
Have you ever been in a situation where you found a lost puppy on the street and didn’t know if it had an owner? Learn how to do it with vector search or image search.
www.elastic.co
이미지 넣은 곳 확인
이미지 넣은 걸로 원래 이미지 중에 일치하는 강아지 찾기
-
elastic docs chatbot with chatGPT
우선 첫 모델 deploy 되어있는지 확인
챗봇이 어디든 필요함
특정 사이트에 대해, 특정 기술에 대해 물어보면 답변 잘 못 해주는데 (그 사업의 자산이기도 하고 학습 데이터 맘대로 크롤링 못해서)
그래서 내 데이터를 넣어서 specific한 답변을 주도록 하는 챗봇이 필요함
자연어처리는 활용하되 데이터는 나가는 건 막아놓을 수 있도록
streamlit
클라우드 계정이... 크롤링이 안되는 경우는 운 안좋게 부정적으로 ~~ 되어서?
새 rule 만들기
- 모두 가져온다? x = disallow , rule = regulation expression
어 밑에꺼랑 반하는 거 아닌가요? -> 위에 있는 거 먼저 실행이라서 ㄱㅊ
영어만 가져오는 규칙 추가
POST search-elastic-docs/_mapping
{
"properties": {
"title-vector": {
"type": "dense_vector",
"dims": 768,
"index": true,
"similarity": "dot_product"
}
}
}
제목만 벡터로 -> title vector
(풀 내용 벡터화 하는 것도 가능하되 오래 걸리겄제)
GET 으로 title-vector 나오는 거 확인 ㄱㄴ
title을 재료로 쓸거다~
얘가 얘로 변환되어서 벡터화 할거야~
쌓이고 있는 거 확인
데이터 이렇게 쌓이고 있구나~ 확인
title
id는 고유 id
current에 버전 쓸 수 있음
이게 title을 벡터화 시킨 것
자연어 검색에 boost 24 줌
중요해서
명확도가 낮다, 구어체로 제목이 되어있는 경우에는 이웃을 늘리는 수밖에 없음 / 키워드나 자연어로 정의할 수 없어서
가이드에 명확한 타이틀이 있기 때문에 k를 1으로 두고 검색 (늘려도 됨)
how to create index 해당될 때 스코어 올라감
수집된 대상에서 document
title만 모아보기
이제 chatGPT 연결하기
검색 대상은 query_text이다~
밑에 model_text랑 같아야 함
ES 데이터가 먼저 오고 chatGPT가 그 쿼리에 대해서 딱 그 정보에 대해서만 answer함
만약 검색이 잘 안됐어, 크롤링을 못했어, 그러면 답변하지 말고 negResponse라고 답하고 끝내~
streamlit -> & 백단에서 실행
IP endpoint 복사해서
밑에 URL에 접속해서 IP 주소 입력하기
그러면 나오는 화면 ↓
한국어로 답변 받는 것
내가 한 건
!pip install googletrans==4.0.0-rc1
하고
from googletrans import Translator
def translate_to_korean(text):
translator = Translator()
translated_text = translator.translate(text, dest='ko').text
return translated_text
# 답변 출력
default_response = get_default_response()
if submit_button:
resp, url = search(query)
prompt = f"Answer this question in korean: {query}\nUsing only the information from this Elastic Doc: {resp}\nIf the answer is not contained in the supplied doc reply '{negResponse}' and nothing else"
answer = chat_gpt(prompt)
# Elasticsearch에서 받아온 답변을 한국어로 번역
translated_answer = translate_to_korean(answer)
if default_response in translated_answer:
st.write(f"ChatGPT: {translated_answer.strip()}")
else:
st.write(f"ChatGPT: {translated_answer.strip()}\n\nDocs: {url}")
이렇게 했는데
prompt = f"Answer this question in korean: {query}\nUsing only the information from this Elastic Doc: {resp}\nIf the answer is not contained in the supplied doc reply '{negResponse}' and nothing else"
in korean 부분만 추가하면 된다!!
그럼 이렇게 됨
근데 한국어로 입력하는 거는 데이터가 다 영어라서 그건 안됨