액세스 승인자액세스 구현자는 정보 시스템이나 네트워크에서 접근 제어와 보안 관리를 담당하는 데 있어 각기 다른 역할을 수행합니다. 이 두 역할을 이해하면, 권한 부여 및 실제 접근의 세부 과정에 대한 명확한 이해를 할 수 있습니다.

1. 액세스 승인자 (Access Approver)

  • 주요 역할: 사용자의 접근 요청을 검토하고 승인하거나 거부하는 권한을 가진 사람 또는 시스템입니다.
  • 책임:
    • 액세스 권한을 필요로 하는 사람의 요청을 평가하여 필요성과 적법성을 판단.
    • 조직의 보안 정책에 따라, 각 사용자가 필요한 권한만 가지도록 접근 수준을 조정.
    • 승인된 요청만을 구현자가 처리할 수 있도록 권한 부여를 관리.
  • 예시:
    • 시스템 관리자, 보안 책임자, 혹은 매니저가 해당 역할을 수행할 수 있습니다.
    • 예를 들어, 특정 직원이 특정 데이터베이스에 접근할 필요가 있는 경우, 매니저가 승인을 할 수 있습니다.

2. 액세스 구현자 (Access Implementer)

  • 주요 역할: 승인자가 승인한 접근 권한을 시스템에 실제로 적용하는 사람 또는 시스템입니다.
  • 책임:
    • 승인된 접근 권한을 시스템에 반영하여 사용자가 요청한 리소스에 접근할 수 있도록 설정.
    • 승인이 없는 권한 요청은 무시하며, 승인된 권한만 적용.
    • 역할 기반 접근 제어(RBAC) 등의 보안 정책을 따라 구현.
  • 예시:
    • IT 관리자 또는 시스템 엔지니어가 주로 이 역할을 수행합니다.
    • 승인자가 승인한 후, IT 담당자가 사용자의 계정에 해당 권한을 부여하는 경우입니다.

차이점 요약

구분액세스 승인자액세스 구현자

역할 접근 요청을 검토하고 승인 여부 결정 승인된 접근 권한을 시스템에 반영
책임 접근 필요성 평가, 정책 준수 확인 승인된 권한만 실제로 구현
접근 제어 관점 승인 프로세스의 시작점 승인 후 적용하는 최종 단계
예시 보안 관리자, 매니저 IT 관리자, 시스템 엔지니어

따라서, 승인자는 "접근 권한을 부여할지 결정"하고, 구현자는 "결정된 접근 권한을 시스템에 적용"하는 차이가 있습니다.

'보안' 카테고리의 다른 글

SOC 2  (0) 2024.03.15

 

MySQL에서 BLOB 타입의 경우, 문자열 길이에 따라 테이블이 차지하는 용량을 계산할 수 있습니다.

4000 Characters를 BLOB로 저장할 때 크기를 계산하는 방법은 다음과 같습니다.

  1. MySQL BLOB 특성:
    • BLOB 타입은 바이너리 데이터(binary data)를 저장합니다.
    • 문자열이 아니라 바이너리 데이터로 저장되므로, 문자 개수가 아니라 바이트 수로 계산합니다.
    • MySQL에서 일반적으로 1 character = 1 byte로 계산되지만, 문자열이 멀티바이트 (UTF-8 등) 문자 집합을 사용한다면 1 character가 1 byte 이상일 수 있습니다.
  2. 4000 Characters가 차지하는 용량:
    • 문자열이 UTF-8로 인코딩된 경우, 문자당 최대 4바이트가 될 수 있습니다.
    • 최악의 경우(모든 문자가 4바이트를 차지하는 경우) 4000 characters × 4 bytes = 16,000 bytes가 됩니다.
    • 따라서 **16,000 bytes (16 KB)**가 됩니다.
  3. 테이블의 크기 계산:
    • MySQL에서 BLOB 칼럼을 갖는 테이블은 칼럼 외에도 인덱스, 테이블 메타데이터 등의 추가 공간을 차지할 수 있습니다.
    • 그러나, 단순히 BLOB 데이터 자체만 계산한다면 위의 16 KB가 해당 데이터의 크기입니다.
  4. MegaBytes로 변환:
    • 16 KB = 0.015625 MB
    • 따라서, 4000 characters의 데이터가 BLOB 컬럼으로 저장된 경우 약 0.016 MB를 차지합니다.

요약하면, BLOB으로 4000 characters를 저장할 때 데이터가 차지하는 대략적인 크기는 약 0.016 MB입니다.

Gemma - Run with Ollama (with Colab)

Google Colab에서 Ollama로 Gemma 실행하기

이 노트북은 Ollama를 사용하여 Gemma 모델에서 추론을 실행하는 방법을 보여줍니다 . Ollama는 로컬에서 LLM을 실행하기 위한 사용하기 쉬운 솔루션이며 Gemma가 기본으로 지원됩니다.

 

Gemma는 Google DeepMind에서 구축한 경량의 최첨단 개방형 모델 제품군입니다. 버전 1.1로 업데이트되었습니다.

Gemma는 2b 및 7b 매개변수 크기로 제공됩니다.

  • ollama run gemma:2b
  • ollama run gemma:7b (default)

gemma 모델정보 확인

gemma 7b

 


gemma 2b

 

Colab 링크

Ollama 설치

공식 설치 스크립트를 통해 Ollama를 설치합니다.

!curl -fsSL https://ollama.com/install.sh | sh
!curl -fsSL https://ollama.com/install.sh | sh
>>> Installing ollama to /usr/local
>>> Downloading Linux amd64 bundle
############################################################################################# 100.0%
>>> Creating ollama user...
>>> Adding ollama user to video group...
>>> Adding current user to ollama group...
>>> Creating ollama systemd service...
WARNING: Unable to detect NVIDIA/AMD GPU. Install lspci or lshw to automatically detect and install GPU dependencies.
>>> The Ollama API is now available at 127.0.0.1:11434.
>>> Install complete. Run "ollama" from the command line.

 

Ollama 시작 (실행)

nohup을 사용하여 백그라운드에서 Ollama를 시작합니다. API 서비스 포트는 11434 입니다.

!nohup ollama serve > ollama.log &
nohup: redirecting stderr to stdout

 

Ollama 모델 목록 확인

!ollama list
NAME    ID    SIZE    MODIFIED

 

추론

명령행(command line)을 이용해서 gemma 7B 모델을 받고 추론을 실행 

!ollama run gemma:7b "대한민국의 수도는 어디야?" 2> ollama.log
대한민국의 수도는 서울입니다.</end_of_turn>

 

영어로 질문해봅니다.

ollama run gemma:7b "What is the capital of Korea?" 2> ollama.log
The capital of Korea is **Seoul**. It is the largest and most populous city in the country.

 

실행한 모델 확인

!ollama list
NAME        ID              SIZE      MODIFIED       
gemma:7b    a72c7f4d0a15    5.0 GB    41 seconds ago

 

REST 엔드포인트를 통해 응답 생성

!curl http://localhost:11434/api/generate -d '{ \
  "model": "gemma:7b", \
  "prompt":"프랑스의 수도는 어디야?" \
}'
{"model":"gemma:7b","created_at":"2024-09-20T07:43:59.191815259Z","response":"프","done":false}
{"model":"gemma:7b","created_at":"2024-09-20T07:43:59.238195689Z","response":"랑","done":false}
{"model":"gemma:7b","created_at":"2024-09-20T07:43:59.284446079Z","response":"스","done":false}
{"model":"gemma:7b","created_at":"2024-09-20T07:43:59.330415772Z","response":"의","done":false}
{"model":"gemma:7b","created_at":"2024-09-20T07:43:59.376395312Z","response":" 수","done":false}
{"model":"gemma:7b","created_at":"2024-09-20T07:43:59.404399661Z","response":"도","done":false}
{"model":"gemma:7b","created_at":"2024-09-20T07:43:59.431299982Z","response":"는","done":false}
{"model":"gemma:7b","created_at":"2024-09-20T07:43:59.45782401Z","response":" 파","done":false}
{"model":"gemma:7b","created_at":"2024-09-20T07:43:59.487122476Z","response":"리","done":false}
{"model":"gemma:7b","created_at":"2024-09-20T07:43:59.514609513Z","response":"(","done":false}
{"model":"gemma:7b","created_at":"2024-09-20T07:43:59.540247914Z","response":"Paris","done":false}
{"model":"gemma:7b","created_at":"2024-09-20T07:43:59.565826889Z","response":")","done":false}
{"model":"gemma:7b","created_at":"2024-09-20T07:43:59.592181701Z","response":"입니다","done":false}
{"model":"gemma:7b","created_at":"2024-09-20T07:43:59.619404725Z","response":".","done":false}
{"model":"gemma:7b","created_at":"2024-09-20T07:43:59.646506512Z","response":"","done":true,"done_reason":"stop","context":[968,2997,235298,559,235298,15508,235313,1645,108,237964,239566,236354,236137,22618,236840,236214,53355,238173,238305,181537,615,235298,559,235298,15508,235313,108,235322,2997,235298,559,235298,15508,235313,2516,108,237964,239566,236354,236137,22618,236840,236214,59994,236432,235278,29437,235275,47555,235265],"total_duration":650239442,"load_duration":39196479,"prompt_eval_count":37,"prompt_eval_duration":114387000,"eval_count":15,"eval_duration":454674000}

 

REST 엔드포인트를 통해 Gemma와 채팅

!curl http://localhost:11434/api/chat -d '{ \
  "model": "gemma:7b", \
  "messages": [ \
    { "role": "user", "content": "스페인의 수도는 어디야?" } \
  ] \
}'
{"model":"gemma:7b","created_at":"2024-09-20T07:44:05.627626051Z","message":{"role":"assistant","content":"스"},"done":false}
{"model":"gemma:7b","created_at":"2024-09-20T07:44:05.673755341Z","message":{"role":"assistant","content":"페"},"done":false}
{"model":"gemma:7b","created_at":"2024-09-20T07:44:05.719617417Z","message":{"role":"assistant","content":"인"},"done":false}
{"model":"gemma:7b","created_at":"2024-09-20T07:44:05.765324012Z","message":{"role":"assistant","content":"의"},"done":false}
{"model":"gemma:7b","created_at":"2024-09-20T07:44:05.810472803Z","message":{"role":"assistant","content":" 수"},"done":false}
{"model":"gemma:7b","created_at":"2024-09-20T07:44:05.842618919Z","message":{"role":"assistant","content":"도"},"done":false}
{"model":"gemma:7b","created_at":"2024-09-20T07:44:05.865453528Z","message":{"role":"assistant","content":"는"},"done":false}
{"model":"gemma:7b","created_at":"2024-09-20T07:44:05.892675721Z","message":{"role":"assistant","content":" 마"},"done":false}
{"model":"gemma:7b","created_at":"2024-09-20T07:44:05.922734686Z","message":{"role":"assistant","content":"드"},"done":false}
{"model":"gemma:7b","created_at":"2024-09-20T07:44:05.94894934Z","message":{"role":"assistant","content":"리"},"done":false}
{"model":"gemma:7b","created_at":"2024-09-20T07:44:05.974847995Z","message":{"role":"assistant","content":"드"},"done":false}
{"model":"gemma:7b","created_at":"2024-09-20T07:44:06.000792996Z","message":{"role":"assistant","content":"입니다"},"done":false}
{"model":"gemma:7b","created_at":"2024-09-20T07:44:06.027347034Z","message":{"role":"assistant","content":"."},"done":false}
{"model":"gemma:7b","created_at":"2024-09-20T07:44:06.054820407Z","message":{"role":"assistant","content":""},"done_reason":"stop","done":true,"total_duration":612398322,"load_duration":38850549,"prompt_eval_count":37,"prompt_eval_duration":104264000,"eval_count":14,"eval_duration":427080000}
 

'AI > LLM-Gemma' 카테고리의 다른 글

Colab에서 T4 GPU 런타임설정 및 Kaggle Credential Key 설정  (0) 2024.09.19
Mac Intel CPU Ollama gemma2  (1) 2024.09.06

설정

Colab 런타임 선택

Gemma 모델을 실행하기에 충분한 리소스가 포함된 Colab 런타임이 필요합니다. 이 경우 T4 GPU를 사용할 수 있습니다.

  1. Colab 창 오른쪽 상단에서 ▾(추가 연결 옵션)을 선택합니다.
  2. "런타임 유형 변경"을 선택합니다.
  3. 하드웨어 가속기에서 T4 GPU를 선택합니다.
런타임 유형 변경

T4 GPU 선택

 


런타임 유형 T4 선택완료

 

Gemma setup

Gemma 설정의 설정 지침을 완료해야 합니다. Gemma 설정 지침은 다음을 수행하는 방법을 보여줍니다.

  • kaggle.com에서 Gemma에 액세스하세요.
  • Gemma 2B 모델을 실행하기에 충분한 리소스가 있는 Colab 런타임을 선택하세요.
  • Kaggle 사용자 이름과 API 키를 Colab 비밀로 생성하고 구성합니다.

Gemma 설정을 완료한 후 다음 섹션으로 이동하여 Colab 환경에 대한 환경 변수를 설정합니다.

 

 

Kaggle API Key 생성

 

1. Kaggle에 로그인한후 Your Profile 선택

My Pofile

2. Settings 클릭해서 이동

3. API 항목중 Create New Token 클릭

4. 로걸에 다운로드된 kaggle.json 파일에서 username과 key값을 저장합니다.

 

{"username":"dongshik","key":"4a566********************9a7be40"}

 

 

자격 증명(credentials) 구성

Kaggle 자격 증명을 Colab Secrets 관리자에 추가하여 안전하게 저장합니다.

 

  1. Google Colab 노트북을 열고 왼쪽 패널에서 🔑 Secrets 탭을 클릭합니다.
  2. 새 비밀번호 만들기 (+새 보안 비밀 추가) : KAGGLE_USERNAME 및 KAGGLE_KEY
  3. 사용자 이름을 KAGGLE_USERNAME에 복사하여 붙여넣으세요.
  4. KAGGLE_KEY에 키를 복사하여 붙여넣으세요.
  5. secret 에 대한 "노트북 액세스"를 허용하려면 왼쪽에 있는 버튼을 전환하세요.
Kaggle API Key 설정

 

Python에서 Kaggel Cerdential key 가져오기

import os
from google.colab import userdata

# Note: `userdata.get` is a Colab API. If you're not using Colab, set the env
# vars as appropriate for your system.
os.environ["KAGGLE_USERNAME"] = userdata.get("KAGGLE_USERNAME")
os.environ["KAGGLE_KEY"] = userdata.get("KAGGLE_KEY")

 

실행했을때 403 Client Error 발생하는경우 kaggle keras gemma 2에 대한 Access 권한이 없기때문입니다.

이럴때 kaggle keara gemma 2로 가서 Access 권한을 요청합니다.

...

You don't have permission to access resource at URL: https://www.kaggle.com/models/keras/gemma2/keras/gemma2_9b_en/2
Please make sure you are authenticated if you are trying to access a private resource or a resource requiring consent.

 

https://www.kaggle.com/models/keras/gemma2

Request Access 클릭

 

 

생략...

Term and Condition Accept

 

권한이 부여된것 확인

'AI > LLM-Gemma' 카테고리의 다른 글

Google Colab에서 Ollama를 사용하여 Gemma 모델을 실행  (0) 2024.09.22
Mac Intel CPU Ollama gemma2  (1) 2024.09.06

 

왼쪽 열의 "장치"에서 기본 폴더에 액세스 할 수 있습니다. 

키보드 키 Cmd + Shift + . (점)를 누릅니다. 

이 키 조합을 누르면 모든 숨김 폴더와 파일이 보입니다.

 

M1 교체 이전에 사용하던 MacBook Pro 2015에서 Ollama로 Gemma2를 구동해봤습니다.

MacBook Pro 2015

 

Processor: Multi-core CPU (Intel i5/i7/i9 or AMD equivalent)
Memory: You should have at least 8 GB of RAM available to run the 7B models, 16 GB to run the 13B models, and 32 GB to run the 33B models.
Storage: At least 20 GB of free space on an SSD
Operating System: Recent versions of Windows, macOS, or Linux

 

Python 3.11.4로 생성된 Conda 가상환경으로 실행합니다.

(base) Gabrielui-MacBookPro:~ gabriel$ conda env list
# conda environments:
#
base                  *  /usr/local/anaconda3
gabriel                  /usr/local/anaconda3/envs/gabriel

(base) Gabrielui-MacBookPro:~ gabriel$ conda activate gabriel
(gabriel) Gabrielui-MacBookPro:~ gabriel$

(gabriel) Gabrielui-MacBookPro:~ gabriel$ python -V
Python 3.11.4

 

세 가지 크기: 2B, 9B 및 27B 파라미터의 모델

셋중에서 9B 모델이 Default 입니다. 

(gabriel) Gabrielui-MacBookPro:~ gabriel$ ollama --version
ollama version is 0.3.9

(gabriel) Gabrielui-MacBookPro:~ gabriel$ ollama run gemma2
pulling manifest
pulling ff1d1fc78170... 100% ▕█████████████████████████████████████████████████████████████████▏ 5.4 GB
pulling 109037bec39c... 100% ▕█████████████████████████████████████████████████████████████████▏  136 B
pulling 097a36493f71... 100% ▕█████████████████████████████████████████████████████████████████▏ 8.4 KB
pulling 2490e7468436... 100% ▕█████████████████████████████████████████████████████████████████▏   65 B
pulling 10aa81da732e... 100% ▕█████████████████████████████████████████████████████████████████▏  487 B
verifying sha256 digest
writing manifest
success
>>>

 

다운로드한 모델을 확인합니다.

(gabriel) Gabrielui-MacBookPro:~ gabriel$ ollama list
NAME         	ID          	SIZE  	MODIFIED
gemma2:latest	ff02c3702f32	5.4 GB	14 minutes ago
(gabriel) Gabrielui-MacBookPro:~ gabriel$

 

 

Ollama + Gemma2 (9B)

ollama run gemma2 로 다운로드한 모델의 정보를 확인합니다.

>>> /show info
  Model
  	arch            	gemma2
  	parameters      	9.2B
  	quantization    	Q4_0
  	context length  	8192
  	embedding length	3584

  Parameters
  	stop	"<start_of_turn>"
  	stop	"<end_of_turn>"

  License
  	Gemma Terms of Use
  	Last modified: February 21, 2024

>>>

 

프롬프트로 질문 "why is the sky blue?"

>>> why is the sky blue?
The sky appears blue due to a phenomenon called **Rayleigh scattering**.

Here's a breakdown:

* **Sunlight:** Sunlight is made up of all the colors of the rainbow.
* **Atmosphere:** When sunlight enters Earth's atmosphere, it collides with tiny air molecules (mainly nitrogen and
oxygen).
* **Scattering:** These molecules scatter the sunlight in all directions.
* **Wavelengths:**  Blue light has a shorter wavelength than other colors in the visible spectrum. Shorter wavelengths are
scattered more effectively by the air molecules.

Therefore, blue light gets scattered much more than other colors, making the sky appear blue to our eyes.

**At sunrise and sunset:** The sunlight travels through more atmosphere to reach us. This means even more blue light is
scattered away, allowing longer wavelengths like orange and red to dominate, resulting in those beautiful hues.

>>> Send a message (/? for help)
Use Ctrl + d or /bye to exit.

 

REST 엔드포인트를 통해 응답 생성

(gabriel) Gabrielui-MacBookPro:~ gabriel$ curl http://localhost:11434/api/generate -d '{
>   "model": "gemma2",
>   "prompt": "Why is the sky blue?"
> }'
{"model":"gemma2","created_at":"2024-09-05T15:30:49.100401Z","response":"The","done":false}
{"model":"gemma2","created_at":"2024-09-05T15:30:49.464952Z","response":" sky","done":false}
{"model":"gemma2","created_at":"2024-09-05T15:30:49.798186Z","response":" appears","done":false}
{"model":"gemma2","created_at":"2024-09-05T15:30:50.143292Z","response":" blue","done":false}



{"model":"gemma2","created_at":"2024-09-05T15:32:05.437344Z","response":" have","done":false}
{"model":"gemma2","created_at":"2024-09-05T15:32:05.785728Z","response":" any","done":false}
{"model":"gemma2","created_at":"2024-09-05T15:32:06.14108Z","response":" other","done":false}
{"model":"gemma2","created_at":"2024-09-05T15:32:06.517148Z","response":" questions","done":false}
{"model":"gemma2","created_at":"2024-09-05T15:32:06.926336Z","response":"!","done":false}
{"model":"gemma2","created_at":"2024-09-05T15:32:07.269795Z","response":"","done":true,"done_reason":"stop","context":[106,1645,108,4385,603,573,8203,3868,235336,107,108,106,2516,108,651,8203,8149,3868,3402,577,476,27171,3151,5231,15599,44957,38497,168428,235248,109,4858,235303,235256,476,25497,235292,109,235287,5231,219715,66058,175521,603,4247,1644,908,576,832,573,9276,576,573,30088,235265,108,235287,5231,30962,235303,235256,117961,66058,3194,33365,30866,573,10379,235303,235256,13795,235269,665,1041,23524,675,16791,2681,24582,591,80711,23584,578,16175,846,108,235287,5231,102164,574,66058,3766,24582,17109,573,33365,575,832,16759,235265,235248,108,235287,5231,10716,181430,235256,66058,7640,2611,919,476,25270,35571,1178,1156,9276,575,573,12918,18303,235265,10323,576,736,235269,665,6803,30390,1683,978,731,573,2681,24582,1178,5543,95178,1154,3118,689,10436,235265,109,688,2339,235269,1212,783,1443,66058,109,651,30390,3868,2611,26676,1167,4628,774,832,16759,235269,3547,573,8203,4824,3868,235265,2625,48825,578,22097,235269,573,33365,37845,1593,978,576,573,13795,235265,1417,3454,573,3868,2611,603,30390,3024,1693,978,235269,15267,573,5543,95178,591,165117,578,72638,235275,577,6378,1167,4628,235269,10241,1941,4964,9276,235265,110,5331,682,1230,1013,692,791,1089,1156,3920,235341],"total_duration":81320587916,"load_duration":42868270,"prompt_eval_count":15,"prompt_eval_duration":3107284000,"eval_count":210,"eval_duration":78169448000}
(gabriel) Gabrielui-MacBookPro:~ gabriel$

 

 

REST 엔드포인트를 통해 Gemma와 채팅

 

(gabriel) Gabrielui-MacBookPro:~ gabriel$ curl http://localhost:11434/api/chat -d '{
>   "model": "gemma2",
>   "messages": [
>     {
>       "role": "user",
>       "content": "why is the sky blue?"
>     }
>   ]
> }'
{"model":"gemma2","created_at":"2024-09-05T15:32:34.118301Z","message":{"role":"assistant","content":"The"},"done":false}
{"model":"gemma2","created_at":"2024-09-05T15:32:34.466319Z","message":{"role":"assistant","content":" sky"},"done":false}
{"model":"gemma2","created_at":"2024-09-05T15:32:34.821353Z","message":{"role":"assistant","content":" appears"},"done":false}
{"model":"gemma2","created_at":"2024-09-05T15:32:35.182394Z","message":{"role":"assistant","content":" blue"},"done":false}
{"model":"gemma2","created_at":"2024-09-05T15:32:35.523289Z","message":{"role":"assistant","content":" due"},"done":false}

{"model":"gemma2","created_at":"2024-09-05T15:33:50.644094Z","message":{"role":"assistant","content":" if"},"done":false}
{"model":"gemma2","created_at":"2024-09-05T15:33:51.039595Z","message":{"role":"assistant","content":" you"},"done":false}
{"model":"gemma2","created_at":"2024-09-05T15:33:51.411561Z","message":{"role":"assistant","content":" have"},"done":false}
{"model":"gemma2","created_at":"2024-09-05T15:33:51.815174Z","message":{"role":"assistant","content":" any"},"done":false}
{"model":"gemma2","created_at":"2024-09-05T15:33:52.152768Z","message":{"role":"assistant","content":" other"},"done":false}
{"model":"gemma2","created_at":"2024-09-05T15:33:52.492949Z","message":{"role":"assistant","content":" questions"},"done":false}
{"model":"gemma2","created_at":"2024-09-05T15:33:52.915517Z","message":{"role":"assistant","content":"!"},"done":false}
{"model":"gemma2","created_at":"2024-09-05T15:33:53.27064Z","message":{"role":"assistant","content":""},"done_reason":"stop","done":true,"total_duration":80946825634,"load_duration":44007406,"prompt_eval_count":15,"prompt_eval_duration":1749943000,"eval_count":190,"eval_duration":79152305000}
(gabriel) Gabrielui-MacBookPro:~ gabriel$

 

 

Ollama + Gemma 1.1 (2B)

 

(gabriel) Gabrielui-MacBookPro:~ gabriel$ ollama run gemma:2b
pulling manifest
pulling manifest
pulling manifest
pulling manifest
pulling manifest
pulling manifest
pulling manifest
pulling manifest
pulling manifest
pulling manifest
pulling manifest
pulling manifest
pulling manifest
pulling manifest
pulling c1864a5eb193... 100% ▕██████████████████████████████████████████████████████████████████████████████████▏ 1.7 GB
pulling 097a36493f71... 100% ▕██████████████████████████████████████████████████████████████████████████████████▏ 8.4 KB
pulling 109037bec39c... 100% ▕██████████████████████████████████████████████████████████████████████████████████▏  136 B
pulling 22a838ceb7fb... 100% ▕██████████████████████████████████████████████████████████████████████████████████▏   84 B
pulling 887433b89a90... 100% ▕██████████████████████████████████████████████████████████████████████████████████▏  483 B
verifying sha256 digest
writing manifest
success
>>> Send a message (/? for help)

 

다운로드한 모델을 확인합니다.

(gabriel) Gabrielui-MacBookPro:~ gabriel$ ollama list
NAME         	ID          	SIZE  	MODIFIED
gemma:2b     	b50d6c999e59	1.7 GB	3 minutes ago
gemma2:latest	ff02c3702f32	5.4 GB	40 minutes ago
(gabriel) Gabrielui-MacBookPro:~ gabriel$

 

 

Gemma2와 동일한 질문을 합니다. "why is the sky blue?"

>>> why is the sky blue?
The sky appears blue due to Rayleigh scattering.

**Rayleigh scattering** is a scattering phenomenon where light waves are scattered in different directions depending on their wavelength.
Blue light has a shorter wavelength than other colors of light, meaning it scatters more effectively. This is why the sky appears blue.

Here's a more detailed explanation:

* **Sunlight** contains all colors of the rainbow.
* **Blue light** has a shorter wavelength than other colors.
* **When blue light** interacts with molecules in the atmosphere, it **scatters more strongly** than other colors.
* This scattering causes blue light to be scattered **towards the observer**.
* The scattered blue light is what we see in the sky as **blue color**.

**Other factors that contribute to the blue color of the sky:**

* **Dust particles:** Air molecules can also scatter light, but their scattering effect is generally weaker than that of molecules in the
atmosphere.
* **Water droplets:** Water droplets in the atmosphere can also scatter light, but their effect is typically less significant than that of
molecules.
* **Sun's position:** The sky appears blue because the sun is lower in the sky, meaning it is directly overhead. This means that more blue
light reaches our eyes.

In summary, the blue color of the sky is due to Rayleigh scattering of light by molecules in the atmosphere, which primarily results from
the shorter wavelength of blue light.

>>> Send a message (/? for help)

 

실행시에 MacBook의 성능을 확인합니다.

 

실행한 모델 정보 확인

>>> /show info
  Model
  	arch            	gemma
  	parameters      	3B
  	quantization    	Q4_0
  	context length  	8192
  	embedding length	2048

  Parameters
  	repeat_penalty	1
  	stop          	"<start_of_turn>"
  	stop          	"<end_of_turn>"

  License
  	Gemma Terms of Use
  	Last modified: February 21, 2024

>>> Send a message (/? for help)

 

Ollama + Gemma 1.1 (7B)

이번엔 Gemma 7B 모델을다운받아 테스트합니다.

(gabriel) Gabrielui-MacBookPro:~ gabriel$ ollama run gemma:7b
pulling manifest
pulling ef311de6af9d...  74% ▕█████████████████████████████████████████
pulling manifest
pulling ef311de6af9d...  74% ▕█████████████████████████████████████████
pulling manifest
pulling ef311de6af9d...  74% ▕█████████████████████████████████████████
pulling manifest
pulling ef311de6af9d... 100% ▕███████████████████████████████████████████████████████████████▏ 5.0 GB
pulling 097a36493f71... 100% ▕███████████████████████████████████████████████████████████████▏ 8.4 KB
pulling 109037bec39c... 100% ▕███████████████████████████████████████████████████████████████▏  136 B
pulling 65bb16cf5983... 100% ▕███████████████████████████████████████████████████████████████▏  109 B
pulling 0c2a5137eb3c... 100% ▕███████████████████████████████████████████████████████████████▏  483 B
verifying sha256 digest
writing manifest
success
>>> Send a message (/? for help)

 

다운로드한 모델 확인

(gabriel) Gabrielui-MacBookPro:~ gabriel$ ollama list
NAME             ID              SIZE      MODIFIED
gemma:7b         a72c7f4d0a15    5.0 GB    2 weeks ago
gemma:2b         b50d6c999e59    1.7 GB    2 weeks ago
gemma2:latest    ff02c3702f32    5.4 GB    2 weeks ago

 

Gemma2와 동일한 질문을 합니다. "why is the sky blue?"

>>> why is the sky blue?
**The sky is blue due to a phenomenon called Rayleigh scattering.**

* Sunlight is composed of all the colors of the rainbow, each with a different wavelength.
* Shorter wavelengths of light, such as blue light, have higher energy and more tightly spaced photons.
* When sunlight interacts with molecules in the atmosphere, such as nitrogen and oxygen, the shorter wavelengths are
scattered more effectively.

**Here's how it works:**

1. Sunlight enters the atmosphere and interacts with molecules of nitrogen and oxygen.
2. These molecules have electrons that can be excited by the energy of the incoming light.
3. The electrons absorb the energy and vibrate, then emit it in all directions.
4. However, **blue light is scattered more efficiently than other colors** because its shorter wavelength allows for more
frequent collisions between the photons and the molecules.

**This scattering process results in:**

* More blue light is scattered in all directions, reaching our eyes and making the sky appear blue.
* Longer wavelengths of light, such as red light, are scattered less efficiently, so we see more of them directly from
the sun.

**Additional factors influencing the sky's color:**

* **Time of day:** The sky is generally bluer at midday when the sunlight travels through less atmosphere.
* **Cloud cover:** Clouds can block the sunlight and scatter less blue light, making the sky appear less blue.
* **Pollution:** Pollution in the atmosphere can also scatter light and affect the sky's color.

>>> Send a message (/? for help)

 

실행한 모델 정보 확인

>>> /show info
  Model
  	arch            	gemma
  	parameters      	9B
  	quantization    	Q4_0
  	context length  	8192
  	embedding length	3072

  Parameters
  	penalize_newline	false
  	repeat_penalty  	1
  	stop            	"<start_of_turn>"
  	stop            	"<end_of_turn>"

  License
  	Gemma Terms of Use
  	Last modified: February 21, 2024

>>> Send a message (/? for help)

 

질의 성능 확인

모델 실행 성능 확인

 

Intel CPU의 MacBook에서 Gemma2 9B 모델 그리고 Gemma 2B, 7B 모델까지 Ollama로 구동해 봤습니다.

감사합니다.

 

 

 

 

 

(llm311) dongsik@dongsikleeui-MacBookPro ~ % cd /Volumes && ll
total 544
drwxr-xr-x   6 root     wheel     192 Sep  5 07:43 .
drwxr-xr-x  20 root     wheel     640 Aug  4 19:31 ..
drwxr-xr-x@  7 dongsik  staff     306 Sep  2 00:58 DBeaver Community
lrwxr-xr-x   1 root     wheel       1 Sep  2 09:31 Macintosh HD -> /
drwx------   1 dongsik  staff   16384 Aug 31 17:54 bpifs
drwx------   1 dongsik  staff  262144 Jan  1  1970 gabriel
(llm311) dongsik@dongsikleeui-MacBookPro /Volumes % pwd
/Volumes

 

관심가는 주제가 있어서 내용 읽어보면서 번역해봅니다.

 

http://www.nltk.org/book_1ed/ch07.html

텍스트에서 정보를 추출하는 간단한 방법은 다음과 같습니다.

 

  1. 텍스트를 문장으로 분할하기
  2. 그 다음 문장을 단어로 토큰화하기 (tokenize)
  3. 각 토큰의 품사(part-of-speech)를 파악하기 (이는 다음 단계를 가능하게 함)
  4. 개체 탐지하기 (Entity detection)
  5. 마지막으로 서로 다른 개체/토큰 간의 관계 파악하기

이러한 단계들을 통해, 우리는 의미 있는 정보를 추출할 수 있게 됩니다. 이 정보는 추가적인 처리에 사용할 수 있으며, 주제 감정 탐지(subject sentiment detection), 주제 식별(theme identification), 사전 생성(dictionary creation) 텍스트 태깅(text tagging) 등과 같은 더 정교한 작업을 수행하는 데 활용할 수 있습니다.

 

이 짧은 글을 통해, 우리는 5단계 정보 추출 과정의 기본 구성 요소를 형성하는 **문법 청킹(Grammar Chunking)**을 탐구하고자 합니다.

 

문법 청킹(Grammar Chunking)은 문장에서 다중 토큰 구문(pharses)을 품사 태깅과 함께 추출하는 기술입니다. 문장은 문장(Setence) → 절(Clauses) → 구(Pharses) → 단어(Words)로 구성된 계층적 문법 구조를 따릅니다. 청킹은 사용자가 의식적으로 또는 무의식적으로 찾고 있는 품사 태그 패턴을 기반으로 문장의 일부, 즉 구를 선택합니다.

 

예를 들어, 모든 문장에는 다섯 가지 주요 "의미 있는 구" 범주가 있습니다 - 명사구(NP), 동사구(VP), 형용사구(ADJP), 부사구(ADVP), 전치사구(PP). 이러한 구 유형을 텍스트에서 추출하고 더 나아가 관계를 설정하거나 개체를 식별하거나 필요에 따라 필터링하면, 80%의 경우에 이 간단한 추출만으로도 텍스트 데이터를 이해하고 다른 NLP 작업을 진행하는 데 필요한 정보를 얻을 수 있습니다.

 

전통적으로 문법 청킹을 수행하는 다양한 방법이 있습니다:

  1. 태그 패턴
  2. 정규 표현식을 이용한 청킹(Chunking)
  3. 텍스트 말뭉치(Corpora)
  4. 규칙 기반 청킹
  5. 통계 기반 청킹

우리는 이를 새로운 응용 머신러닝 관점에서 살펴볼 것입니다. 모든 프로그래밍 복잡성을 숨기기 위해 - 우리는 spaCy 라이브러리를 사용할 것입니다 (spaCy는 고급 NLP를 위한 무료 오픈 소스 라이브러리입니다. 빠르고 정확합니다). 이 라이브러리는 위에서 나열한 5단계를 수행하기 위한 매우 사용하기 쉬운 인터페이스를 제공합니다.

물론, 내장 라이브러리의 경우와 마찬가지로 우리는 특정한 유연성을 잃게 되지만, 일부 유연성을 회복하기 위해 추가적인 프로그래밍을 어떻게 구축하는지도 간단히 다룰 것입니다.

 

우리는 해결책을 개발하기 위해 Python과 Jupyter Notebook을 사용할 것입니다. 데이터는 스크랩한 샘플 뉴스 기사가 될 것입니다. Jupyter Notebook과 사용된 샘플 데이터는 GitHub에서 액세스할 수 있습니다.

 

(이 접근 방식을 통해 실제 데이터로 작업하면서 spaCy를 사용한 NLP 작업을 실습할 수 있습니다. GitHub 저장소를 통해 코드와 데이터를 쉽게 공유하고 접근할 수 있어, 다른 사람들도 이 예제를 따라 해볼 수 있습니다.)

 

몇 가지 필요한 라이브러리를 임포트하는 것으로 시작하겠습니다.

 

import pandas as pd, os, re, string
import numpy as np
import spacy

#'en_core_web_md' is a General-purpose pretrained model to predict named entities, 
#part-#of-speech tags and syntactic dependencies. 
#Can be used out-of-the-#box and fine-tuned on more specific data.

nlp = spacy.load('en_core_web_md')
comp=pd.read_excel(r'C:\Saurabh\Publication\Chunking\Chunk_data.xlsx')
print(len(comp))
print(comp.dtypes)
print(comp['Text'].astype(str))
2
Text    object
dtype: object
0    Ruth Bader Ginsburg was an associate justice o...
1    I opened a savings account at Wells Fargo in D...

 

Ruth Ginsberg에 관한 첫 번째 샘플 단락을 사용하여 개념을 설명하겠습니다. 참고로, 우리는 'en_core_web_md'라는 spaCy의 범용 사전 학습된 모델을 사용하여 명명된 엔티티(named entities), 품사 태그(part-of-speech tags), 구문적 의존성(syntactic dependencies)을 예측합니다. 이 모델은 바로 사용할 수 있으며, 더 특정한 데이터에 맞춰 미세 조정할 수도 있습니다.

 

이제 문장 토크나이저를 사용하여 문장을 추출해보겠습니다.

 

comp['sentence'] = comp['Text'].apply(lambda x: sent_tokenize(x))
print(len(comp['sentence'][0]))
comp['sentence_clean'] = comp['sentence']
print(comp['sentence_clean'])
comp_subset = pd.DataFrame(comp['sentence_clean'][0], columns=['sentence_clean'])
comp_subset
2
0    [Ruth Bader Ginsburg was an associate justice ...
1    [I opened a savings account at Wells Fargo in ...

 

텍스트를 문장 목록으로 변환한 것을 볼 수 있습니다. 확장 가능한 프로세스를 설정하기 위해 문장을 세로형 Dataframe으로 변환합니다. 샘플 단락에 대해 설정하고 있지만, 이 작업의 목적을 이해하시리라 생각합니다. 이 방식은 여러 단락과 문장에 대해 적용할 수 있습니다.

 

comp_subset = pd.DataFrame(comp['sentence_clean'][0], columns=['sentence_clean'])
comp_subset

 

이제 다음 두 단계를 진행하겠습니다. 단어 토큰화(tokenization)와 품사 태깅(POS tagging)입니다. spaCy를 사용하면 이 작업이 얼마나 쉬운지 확인해보세요. onegram 메서드는 단어(토큰), 품사 태깅, 그리고 텍스트 분석 작업에서 유용한 다양한 정보를 출력합니다. 또한 이 메서드가 토큰과 품사를 어떻게 반환하는지도 주목해보세요. 나중에 n-grams을 생성해야 할 경우, n-grams과 품사 태깅을 생성하는 방법으로 이 메서드를 확장하는 방법도 보여드리겠습니다.

 

def onegram(text):
    doc = nlp(text)
    result = []
    print("{0:20} {1:20} {2:8} {3:8} {4:8} {5:8} {6:8} {7:8}".format("text", "lemma_", "pos_", "tag_", "dep_",
            "shape_", "is_alpha", "is_stop"))
    for token in doc:
        print("{0:20} {1:20} {2:8} {3:8} {4:8} {5:8} {6:8} {7:8}".format(token.text, token.lemma_, token.pos_, token.tag_, token.dep_,
            token.shape_, token.is_alpha, token.is_stop))
        #print(token.text, token.lemma_, token.pos_, token.tag_, token.dep_,
            #token.shape_, token.is_alpha, token.is_stop)
        result.append((token.text, token.tag_))
    return result
comp_subset = comp_subset[comp_subset.index==0]
comp_subset.head(1)['sentence_clean'].apply(onegram)

 

 

이 메서드는 실제 토큰(예: "was"), 어간(즉, 토큰의 기본형, 예: "be"), 품사(AUX), 품사 태깅(VBD), 문장에서 다른 단어에 대한 의존성(ROOT), 형태(즉, 소문자로 시작하는지, 알파벳만 있는지, 그리고 불용어인지 여부)를 제공합니다. 단 두 줄의 코드로 이 모든 정보를 얻을 수 있다는 것은 정말 놀랍습니다! 만약 NLTK를 사용해 본 적이 있다면, 이러한 정보를 얻기 위해 얼마나 많은 코드를 작성해야 하는지 아실 겁니다. 그리고 이 정보들은 매우 중요합니다. 불용어를 제거하고, 알파벳이 아닌 텍스트를 정리하며, 텍스트를 표제화(lemmatize)하고, 패턴을 교정하는 데 사용할 수 있습니다.

 

이제 우리의 목표로 돌아가서, 우리는 토큰과 품사를 얻었습니다. 그렇다면 한 단계 더 나아가 특정 패턴을 가진 단어 그룹(예: 명사구)을 식별할 수 있는 방법은 무엇일까요? 명사구(NP)는 선택적 한정사(DT) 뒤에 여러 형용사(JJ)가 오고 그 다음에 명사(NN)가 오는 단어들의 연속입니다.

def extractNP(text):
    doc = nlp(text)
    result = []
    for np in doc.noun_chunks:
        result.append(np.text)
    print(result)
    return result
comp_subset['sentence_clean'].apply(extractNP)
['Ruth Bader Ginsburg', 'an associate justice', 'the U.S. Supreme Court', 'nearly three decades']

 

이 출력은 문장 내의 모든 명사구를 보여줍니다. spaCy는 내장된 명사 청커를 제공하지만, 동사구, 형용사구 또는 특정 문법 패턴에 기반한 구가 필요한 경우, spaCy가 제공하는 토큰과 품사 정보를 사용하여 사용자 정의 함수를 만들 수 있습니다.

이제 정보 추출의 다음 단계로 넘어가 보겠습니다 - 서로 다른 토큰 간의 구문적 관계(syntactic relationship detection)를 탐지하는 것입니다. 이를 통해 우리는 문장 구조를 더 잘 이해하고 필요에 따라 특정 부분을 선택적으로 활용할 수 있습니다.

 

from spacy import displacy
def getdependency(text):
    doc = nlp(text)
    print("{0:20} {1:20} {2:20} {3:20} {4:30}".format("text", "dep_", "head", "head_pos_", "children"))
    for token in doc:
        print("{0:20} {1:20} {2:20} {3:20} {4:30}".format(token.text, token.dep_, token.head.text, token.head.pos_, 
                                                 " ".join([str(child) for child in token.children])))
    return
def getdisplay(text):
    doc = nlp(text)
    displacy.serve(doc, style="dep")
    return
comp_subset['sentence_clean'].apply(getdependency)
comp_subset['sentence_clean'].apply(getdisplay)

 

 

 

테이블과 시각 자료를 모두 읽어 head, children, 그리고 의존성을 이해할 수 있어야 합니다. 이 문장의 일부에서 Ginsburg는 명사 주어이며, Ruth와 Bader 모두 이에 의존합니다. "was"는 Ruth를 그녀의 직업인 justice(associate justice)와 연결하는 root입니다. 이는 문장의 일부에 대한 매우 간단한 해석입니다 - 다양한 열 제목의 의미를 이해하기 위해 추가 학습을 하시기를 권합니다. 그래야 직접 더 잘 해석할 수 있는 위치에 있게 될 것입니다.

관계 탐지는 중요하고 유용합니다 - 예를 들어, 감정 분석을 수행하고 있고 각 주제에 대한 작성자의 감정을 이해해야 한다고 가정해 봅시다. 이런 시나리오에서는 각 주제와 그 주제와 관련된 단어들을 식별할 수 있는 능력이 핵심이 됩니다.

 

마지막 부분인 개체 탐지로 넘어가겠습니다. 명명된 개체는 이름이 지정된 "실제 세계의 객체"입니다 - 예를 들어, 사람, 국가, 제품 또는 책 제목 등입니다. spaCy는 모델에 예측을 요청함으로써 문서 내의 다양한 유형의 명명된 개체(named entities)를 인식할 수 있습니다. 모델은 통계적이며 학습된 예제에 크게 의존하기 때문에, 이것이 항상 완벽하게 작동하는 것은 아니며 사용 사례에 따라 나중에 약간의 조정이 필요할 수 있습니다.

예를 들어, 문서 파싱 문제(예: 이력서 파싱)에 대해 작업하고 있고 사람이 공부한 학교 이름과 위치를 식별해야 한다고 가정해 봅시다. 이런 경우 개체 탐지가 유용할 것입니다. 이를 통해 문장을 실제 세계의 정보와 연결할 수 있습니다.

 

def getEntity(text):
    doc = nlp(text)
    for ent in doc.ents:
        print(ent.text, ent.start_char, ent.end_char, ent.label_)
    return
comp_subset['sentence_clean'].apply(getEntity)

 

 

개체 탐지를 통해 이제 Ruth Bader Ginsburg를 사람으로, U.S. Supreme Court를 조직으로 식별할 수 있습니다! 그리고 관계 탐지를 통해 Ruth가 associate justice라는 것을 알 수 있습니다. 따라서 이제 여러분과 기계는 Ruth Bader Ginsburg가 U.S. Supreme Court의 associate justice라는 것을 알 수 있게 되었습니다!

 

이 글이 마음에 들고 도움이 된다고 생각하신다면, 박수를 보내주세요!

 

저자 소개

Dr. Mahendra NayakMr. Saurabh Singh는 Accenture Applied Intelligence, 방갈로르의 수석 데이터 과학자입니다. 그들은 주로 대규모 비정형 데이터, 예측 모델링, 기계 학습, 그리고 기업 규모의 지능형 시스템 구축 분야에서 일하고 있습니다.

 

https://medium.com/@saurabhsingh_23777/grammar-chunking-and-text-information-extraction-140cd796d73b

 

Grammar Chunking and Text Information Extraction

Author: Dr. Mahendra Nayak and Saurabh Singh

medium.com

 

 

https://unstructured-io.github.io/unstructured/index.html

 

Unstructured 0.13.0 documentation

Next Introduction

unstructured-io.github.io

 

Unstructured 라이브러리는 downstream machine learning tasks에서 사용할 수 있도록 비구조화 텍스트 문서를 전처리하고 구조화하는 데 도움을 주도록 설계되었습니다. Unstructured 라이브러리를 사용하여 처리할 수 있는 문서 예시에는 PDF, XML 및 HTML 문서가 포함됩니다

 

Downstream Task 의미
구체적으로 풀고 싶은 문제들을 말한다.
최근 자연어 처리분야에서는 언어모델을 프리트레인(pre-train)방식을 이용해 학습을 진행하고, 그 후에 원하고자 하는 태스크를 파인 튜닝(fine-tuning) 방식을 통해 모델을 업데이트 하는 방식을 사용하는데 이때, 태스크를 다운스트림 태스크라 한다.
예를들어, 버트의 언어모델을 질의응답 태스크인 squad를 학습한다고 할때, 이때 질의응답 태스크를 다운스트림 태스크로 볼 수 있을것이다.

Core Functionality

Unstructured 라이브러리에는 원시(raw) 소스 문서를 분할, 청크, 정리 및 스테이징하는 기능이 포함되어 있습니다. 이러한 기능은 라이브러리 내에서 주요 공개 인터페이스로 작동합니다. 이 섹션을 읽은 후에는 다음을 이해할 수 있어야 합니다.

 

  • How to partition a document into json or csv.
    문서를 JSON 또는 CSV로 분할하는 방법:
    - Unstructured 라이브러리의 분할 함수를 사용하여 문서를 원하는 형식(JSON 또는 CSV)으로 분할할 수 있습니다. 이 함수는 문서를 적절한 크기로 나누고 각 부분을 원하는 형식으로 저장합니다.

  • How to remove unwanted content from document elements using cleaning functions.
    문서 요소에서 불필요한 내용을 제거하는 방법:
    - Unstructured 라이브러리의 정리 함수를 사용하여 문서 요소에서 불필요한 내용을 제거할 수 있습니다. 이 함수는 지정된 규칙에 따라 문서를 정리하고, 특정 패턴이나 문자열을 제거하여 요소를 정제합니다.

  • How to extract content from a document using the extraction functions.
    문서에서 콘텐츠를 추출하는 방법:
    - Unstructured 라이브러리의 추출 함수를 사용하여 문서에서 콘텐츠를 추출할 수 있습니다. 이 함수는 특정 유형의 데이터(예: 텍스트, 이미지, 표 등)를 문서에서 식별하고 추출합니다.

  • How to prepare data for downstream use cases using staging functions
    스테이징 기능을 사용하여 downstream 사용 사례에 대한 데이터를 준비하는 방법:
    -
    Unstructured 라이브러리의 스테이징 함수를 사용하여 downstream 사용 사례에 데이터를 준비할 수 있습니다. 이 함수는 추출된 콘텐츠를 적절한 형식으로 구성하고 저장하며, 후속 기계 학습 작업에 사용할 수 있는 형식으로 데이터를 준비합니다.
  • How to chunk partitioned documents for use cases such as Retrieval Augmented Generation (RAG).
    RAG(검색 보강 생성)과 같은 사용 사례를 위해 문서를 청크로 분할하는 방법:
    - Unstructured 라이브러리의 청크 함수를 사용하여 문서를 필요한 크기로 청크로 나눌 수 있습니다. 이 함수는 문서를 적절한 크기의 청크로 분할하여 특정 사용 사례에 적합하도록 준비합니다. RAG와 같은 사용 사례를 위해 필요한 크기로 문서를 청크로 분할할 수 있습니다.

 

https://github.com/Unstructured-IO/unstructured/blob/main/README.md

 

unstructured/README.md at main · Unstructured-IO/unstructured

Open source libraries and APIs to build custom preprocessing pipelines for labeling, training, or production machine learning pipelines. - Unstructured-IO/unstructured

github.com

Open-Source Pre-Processing Tools for Unstructured Data

구조화되지 않은 라이브러리는 PDF, HTML, Word 문서 등과 같은 이미지와 텍스트 문서를 수집하고 전처리하기 위한 오픈 소스 구성 요소를 제공합니다. 구조화되지 않은 사용 사례는 LLM의 데이터 처리 워크플로를 간소화하고 최적화하는 데 중점을 두고 있습니다. 비정형 모듈식 기능 및 커넥터는 데이터 수집 및 전처리를 단순화하는 응집력 있는 시스템을 형성하여 다양한 플랫폼에 적응할 수 있고 비정형 데이터를 정형 출력으로 변환하는 데 효율적입니다.

 

다중문서 처리에 아주좋은 라이브러리입니다. 

 

다른 스터디와 병행해서 문서를 계속 업데이트 할예정입니다.

 

Note!!!

Unstructured io를 이용해서 PDF로 OpenAI를 이용한 Multi modal 활용은 아래 페이지를 참조하세요.

https://amnesia.tistory.com/64

 

대용량 PDF를 위한 unstructured와 Multi-modal RAG에 대한 심층 분석

Overview끊임없이 진화하는 인공 지능 환경에서 보다 인간과 유사한 대화 에이전트를 만드는 것이 중심 초점이었습니다. 텍스트 기반 상호 작용이 크게 발전했지만 텍스트, 이미지

amnesia.tistory.com

 

Overview

끊임없이 진화하는 인공 지능 환경에서 보다 인간과 유사한 대화 에이전트를 만드는 것이 중심 초점이었습니다. 텍스트 기반 상호 작용이 크게 발전했지만 텍스트, 이미지, 문서 등 다양한 양식을 통합하면 사용자 경험이 더욱 풍부해지고 에이전트의 효과적인 이해 및 대응 능력이 향상됩니다. 이 영역에서 유망한 접근 방식 중 하나는 다중 모드 표현의 기능과 생성 모델의 기능을 통합하는 다중 모드 검색 증강 생성(Multi-modal Retrieval-Augmented Generative, RAG) 모델을 활용하는 것입니다.

이 글에는 angchain’s cookbook에 있는 Multi-Modal RAG의 재구현과 심층적인 설명이 포함되어 있습니다.

 

Understanding Multi-modal RAG

검색 강화 생성 모델(Retrieval-Augmented Generative models) 또는 RAG의 개념은 transformer와 같은 생성 모델의 강점과 검색 기반(retrieval-based) 기술을 결합할 수 있는 능력 덕분에 주목받고 있습니다.

검색기 구성 요소(retriever components)로 생성 모델을 강화함(augmenting)으로써 RAG 모델은 대규모 텍스트 말뭉치(corpora)기존 지식을 효과적으로 활용하여 응답을 향상시킬 수 있습니다.

 

이제 이 패러다임을 다중 모드 설정으로 확장한 Multi-modal RAG는 텍스트, 이미지, 문서와 같은 다양한 형식을 검색 및 생성 프로세스에 통합합니다. 이를 통해 대화 에이전트는 텍스트 입력뿐만 아니라 그에 수반되는 시각적 또는 문맥 정보를 기반으로 응답을 이해하고 생성할 수 있습니다.

 

설치

pip install "unstructured[all-docs]"

% pip list | grep unstructured
unstructured                             0.13.2
unstructured-client                      0.18.0
unstructured-inference                   0.7.25
unstructured.pytesseract                 0.3.12

 

Lets dive into technicalities

Multi-modal RAG 기반 대화 에이전트를 달성하기 위해 단계:

https://github.com/SunGajiwala/langchain/blob/master/cookbook/Multi_modal_RAG.ipynb

 

  1. Extract text, tables, and images from PDF files using partitioning techniques and document structure analysis.
    분할 기술과 문서 구조 분석을 사용하여 PDF 파일에서 텍스트, 표 및 이미지를 추출

  2. Categorize extracted elements into text and tables based on their type.
    추출된 요소를 유형에 따라 텍스트와 테이블로 분류

  3. Generate summaries for text elements using an OpenAI model, optionally splitting long texts into manageable chunks.
    OpenAI 모델을 사용하여 텍스트 요소에 대한 요약을 생성하고 선택적으로 긴 텍스트를 관리 가능한 덩어리로 분할

  4. Encode images as base64 strings and summarize them using an OpenAI Vision model.
    이미지를 base64 문자열로 인코딩하고 OpenAI Vision 모델을 사용하여 요약

  5. Create a multi-vector retriever to index summaries and raw contents of text, tables, and images.
    텍스트, 표, 이미지의 요약과 원시 콘텐츠를 색인화하는 다중 벡터 검색기를 생성

  6. Initialize a vector store using the Chroma vector store with OpenAI embeddings.
    OpenAI 임베딩이 포함된 Chroma 벡터 저장소를 사용하여 벡터 저장소를 초기화

  7. Construct a multi-modal RAG chain for processing user questions with both textual and visual context.
    텍스트 및 시각적 컨텍스트를 모두 사용하여 사용자 질문을 처리하기 위한 다중 모드 RAG 체인을 구축

  8. Retrieve relevant documents based on a user query using the multi-vector retriever.
    다중 벡터 검색기를 사용하여 사용자 쿼리를 기반으로 관련 문서를 검색

  9. Invoke the multi-modal RAG chain to generate a response to the user query.
    다중 모드 RAG 체인을 호출하여 사용자 쿼리에 대한 응답을 생성
from langchain.text_splitter import CharacterTextSplitter
from unstructured.partition.pdf import partition_pdf


# Extract elements from PDF
def extract_pdf_elements(path, fname):
    """
    Extract images, tables, and chunk text from a PDF file.
    path: File path, which is used to dump images (.jpg)
    fname: File name
    """
    return partition_pdf(fname,
                        extract_images_in_pdf=True,
                        infer_table_structure=True,
                        chunking_strategy="by_title",
                        max_characters=4000,
                        new_after_n_chars=3800,
                        combine_text_under_n_chars=2000
    )

# Categorize elements by type
def categorize_elements(raw_pdf_elements):
    """
    Categorize extracted elements from a PDF into tables and texts.
    raw_pdf_elements: List of unstructured.documents.elements
    """
    tables = []
    texts = []
    for element in raw_pdf_elements:
        #print(element)
        #print(str(type(element)))
        if "unstructured.documents.elements.Table" in str(type(element)):
            print(str(type(element)))
            tables.append(str(element))
        elif "unstructured.documents.elements.CompositeElement" in str(type(element)):
            print(str(type(element)))
            texts.append(str(element))
    return texts, tables


# File path
fpath = "/Users/dongsik/github/Multi-Modal-using-RAG/Attention_is_all_you_need.pdf"
fname = "Attention_is_all_you_need.pdf"

# Get elements
raw_pdf_elements = extract_pdf_elements(fpath, fname)
#print(raw_pdf_elements)

# Get text, tables
texts, tables = categorize_elements(raw_pdf_elements)

# Optional: Enforce a specific token size for texts
text_splitter = CharacterTextSplitter.from_tiktoken_encoder(
    chunk_size=4000, chunk_overlap=0
)
joined_texts = " ".join(texts)
texts_4k_token = text_splitter.split_text(joined_texts)

 

1. extract_pdf_elements 함수는 unstructured.partition.pdf 모듈의 partition_pdf 메서드를 활용하여 PDF 파일에서 이미지, 테이블 및 청크 텍스트를 추출합니다.

 

2. categorize_elements 함수는 추출된 요소를 유형에 따라 텍스트와 테이블로 분류합니다.

 

3. 선택적으로 추출된 텍스트를 CharacterTextSplitter 클래스를 사용하여 특정 토큰 크기의 청크로 분할할 수 있습니다. 이 단계에는 청크 크기 및 겹침과 같은 매개변수를 사용하여 텍스트 분할기를 설정한 다음 결합된 텍스트를 청크로 분할하는 작업이 포함됩니다.

 

pdf에서 추출된 요소항목을 확인해보겠습니다.

print("raw_pdf_elements : ", raw_pdf_elements)
print(raw_pdf_elements[0].metadata)

import pandas as pd
# Convert JSON output into Pandas DataFrame
data = []
for c in raw_pdf_elements:
    #print(type(c).__name__)
    row = {}
    row['Element Type'] = type(c).__name__
    row['Filename'] = c.metadata.filename
    row['Date Modified'] = c.metadata.last_modified
    row['Filetype'] = c.metadata.filetype
    row['Page Number'] = c.metadata.page_number
    row['text'] = c.text
    data.append(row)
df = pd.DataFrame(data)
print(len(df))
df.to_excel('attention_is_all_you_need.xlsx', index=False)

 

raw_pdf_elements :  
[<unstructured.documents.elements.CompositeElement object at 0x35524b590>, 
 <unstructured.documents.elements.CompositeElement object at 0x30a24a650>, 
 <unstructured.documents.elements.CompositeElement object at 0x3557f9090>, 
 <unstructured.documents.elements.CompositeElement object at 0x355704650>, 
 <unstructured.documents.elements.CompositeElement object at 0x355704fd0>, 
 <unstructured.documents.elements.CompositeElement object at 0x3557055d0>, 
 <unstructured.documents.elements.Table object at 0x30ef5d3d0>, 
 <unstructured.documents.elements.CompositeElement object at 0x355706e10>, 
 <unstructured.documents.elements.CompositeElement object at 0x30ef75290>, 
 <unstructured.documents.elements.CompositeElement object at 0x30ef77650>, 
 <unstructured.documents.elements.Table object at 0x30ef76290>, 
 <unstructured.documents.elements.CompositeElement object at 0x3449ed510>, 
 <unstructured.documents.elements.CompositeElement object at 0x3449edc50>, 
 <unstructured.documents.elements.Table object at 0x3449efd10>, 
 <unstructured.documents.elements.CompositeElement object at 0x355b57350>, 
 <unstructured.documents.elements.Table object at 0x355b54c90>, 
 <unstructured.documents.elements.CompositeElement object at 0x3559d2250>, 
 <unstructured.documents.elements.CompositeElement object at 0x3559d1b50>, 
 <unstructured.documents.elements.CompositeElement object at 0x107cd4350>, 
 <unstructured.documents.elements.CompositeElement object at 0x307a4a010>]
 
<unstructured.documents.elements.ElementMetadata object at 0x32255e810>

20

 

unstructured.documents.elements.Table : Table

unstructured.documents.elements.CompositeElement : Text

 

추출된 요소를 dataframe에 넣고 excel로 출력해보면 Chunking 옵션에 맞게 추출된것을 확인할수있습니다.

 

원본 pdf (10 page에 있는 table)

 

pdf에서 추출된 요소(elements)

 

 

from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
import os

# OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
# Generate summaries of text elements
def generate_text_summaries(texts, tables, summarize_texts=False):
    """
    Summarize text elements
    texts: List of str
    tables: List of str
    summarize_texts: Bool to summarize texts
    """

    # Prompt
    prompt_text = """You are an assistant tasked with summarizing tables and text for retrieval. \
    These summaries will be embedded and used to retrieve the raw text or table elements. \
    Give a concise summary of the table or text that is well optimized for retrieval. Table or text: {element} """
    prompt = ChatPromptTemplate.from_template(prompt_text)

    # Text summary chain
    model = ChatOpenAI(temperature=0, model="gpt-4")
    summarize_chain = {"element": lambda x: x} | prompt | model | StrOutputParser()

    # Initialize empty summaries
    text_summaries = []
    table_summaries = []

    # Apply to text if texts are provided and summarization is requested
    if texts and summarize_texts:
        text_summaries = summarize_chain.batch(texts, {"max_concurrency": 5})
    elif texts:
        text_summaries = texts

    # Apply to tables if tables are provided
    if tables:
        table_summaries = summarize_chain.batch(tables, {"max_concurrency": 5})

    return text_summaries, table_summaries


# Get text, table summaries
text_summaries, table_summaries = generate_text_summaries(
    texts_4k_token, tables, summarize_texts=True
)

 

 

1. generate_text_summaries 함수는 텍스트 요소를 요약할지 여부를 나타내는 bool 플래그 summarize_texts와 함께 텍스트 및 테이블 요소 목록을 입력으로 사용합니다. 요약 작업을 위한 프롬프트 템플릿을 설정합니다.

 

2. Prompt template에는 검색에 최적화된 간결한 요약을 제공하도록 안내하는 assistant에 대한 instructions이 포함되어 있습니다.

 

3. 이 코드는 temperature 및 model variant("gpt-3.5-turbo-16k")과 같은 매개변수를 지정하여 OpenAI 모델과의 채팅 기반 상호 작용을 초기화합니다. prompt template, OpenAI 모델, 모델의 응답을 처리하기 위한 output parser로 구성된 요약 체인이 구성됩니다.

 

4. text element가 제공되고 요약이 요청되면 요약 체인이 텍스트 요소에 일괄적으로 적용됩니다. max_concurrency 매개변수는 OpenAI API에 대한 최대 동시 요청 수를 제어합니다.

 

5. table element가 제공되면 요약 체인이 유사하게 적용됩니다.

 

6. 마지막으로, 전처리된 text element (texts_4k_token), 테이블 및 텍스트 요소를 요약하는 플래그와 함께 generate_text_summaries 함수를 호출합니다.

 

import base64
import os

from langchain_core.messages import HumanMessage


def encode_image(image_path):
    """Getting the base64 string"""
    with open(image_path, "rb") as image_file:
        return base64.b64encode(image_file.read()).decode("utf-8")


def image_summarize(img_base64, prompt):
    """Make image summary"""
    chat = ChatOpenAI(model="gpt-4-vision-preview", max_tokens=200)

    msg = chat.invoke(
        [
            HumanMessage(
                content=[
                    {"type": "text", "text": prompt},
                    {
                        "type": "image_url",
                        "image_url": {"url": f"data:image/jpeg;base64,{img_base64}"},
                    },
                ]
            )
        ]
    )
    return msg.content


def generate_img_summaries(path):
    """
    Generate summaries and base64 encoded strings for images
    path: Path to list of .jpg files extracted by Unstructured
    """

    # Store base64 encoded images
    img_base64_list = []

    # Store image summaries
    image_summaries = []

    # Prompt
    from tqdm import tqdm
    import time

    prompt = """You are an assistant tasked with summarizing images for retrieval. \
        These summaries will be embedded and used to retrieve the raw image. \
        Give a concise summary of the image that is well optimized for retrieval."""

    count = 0

    for img_file in tqdm(sorted(os.listdir(path)), desc="Processing images"):
        if img_file.endswith(".jpg"):
            img_path = os.path.join(path, img_file)

            try:
                base64_image = encode_image(img_path)
                img_base64_list.append(base64_image)
                image_summaries.append(image_summarize(base64_image, prompt))
                count += 1

            except Exception as e:
                print(f"Error processing image {img_file}: {e}")

    return img_base64_list, image_summaries


# Image summaries
img_base64_list, image_summaries = generate_img_summaries("figures/")

 

1. encode_image 함수는 지정된 경로에서 이미지 파일을 읽고 이를 base64 문자열로 인코딩합니다. 인코딩된 문자열은 UTF-8 형식으로 디코딩된 후 반환됩니다.

 

2. image_summarize 함수는 base64로 인코딩된 이미지와 프롬프트를 입력으로 사용합니다. GPT-4 Vision 모델로 채팅 세션을 초기화하고 프롬프트와 base64 형식으로 인코딩된 이미지 URL을 모두 포함하는 메시지를 구성합니다.

 

3. generate_img_summaries 함수는 JPEG 이미지가 포함된 디렉터리를 처리합니다. 각 이미지 파일을 반복하여 base64 형식으로 인코딩하고 image_summarize 함수를 사용하여 요약을 생성합니다.

 

4. 프롬프트는 generate_img_summaries 함수 내에 정의되어 검색에 최적화된 간결한 요약을 제공하도록 assistant에게 지시합니다. tqdm 라이브러리는 이미지 처리 중에 진행률 표시줄을 표시하는 데 사용됩니다.

 

5. 마지막으로 이미지가 포함된 디렉터리 경로를 사용하여 generate_img_summaries 함수가 호출됩니다. 이는 이미지 요약을 위해 GPT-4 Vision 모델을 활용하여 각 이미지에 대해 base64로 인코딩된 이미지와 요약을 생성합니다.

 

import uuid

from langchain.retrievers.multi_vector import MultiVectorRetriever
from langchain.storage import InMemoryStore
from langchain_community.vectorstores import Chroma
from langchain_core.documents import Document
from langchain_openai import OpenAIEmbeddings


def create_multi_vector_retriever(
    vectorstore, text_summaries, texts, table_summaries, tables, image_summaries, images
):
    """
    Create retriever that indexes summaries, but returns raw images or texts
    """

    # Initialize the storage layer
    store = InMemoryStore()
    id_key = "doc_id"

    # Create the multi-vector retriever
    retriever = MultiVectorRetriever(
        vectorstore=vectorstore,
        docstore=store,
        id_key=id_key,
    )

    # Helper function to add documents to the vectorstore and docstore
    def add_documents(retriever, doc_summaries, doc_contents):
        doc_ids = [str(uuid.uuid4()) for _ in doc_contents]
        summary_docs = [
            Document(page_content=s, metadata={id_key: doc_ids[i]})
            for i, s in enumerate(doc_summaries)
        ]
        retriever.vectorstore.add_documents(summary_docs)
        retriever.docstore.mset(list(zip(doc_ids, doc_contents)))

    # Add texts, tables, and images
    # Check that text_summaries is not empty before adding
    if text_summaries:
        add_documents(retriever, text_summaries, texts)
    # Check that table_summaries is not empty before adding
    if table_summaries:
        add_documents(retriever, table_summaries, tables)
    # Check that image_summaries is not empty before adding
    if image_summaries:
        add_documents(retriever, image_summaries, images)

    return retriever


# The vectorstore to use to index the summaries
vectorstore = Chroma(
    collection_name="rag-storage", embedding_function=OpenAIEmbeddings()
)

# Create retriever
retriever_multi_vector_img = create_multi_vector_retriever(
    vectorstore,
    text_summaries,
    texts,
    table_summaries,
    tables,
    image_summaries,
    img_base64_list,
)

 

1. create_multi_Vector_retriever 함수는 텍스트 요약, 텍스트 내용, 테이블 요약, 테이블 내용, 이미지 요약 및 이미지 base64 인코딩 문자열을 포함하여 다양한 요약 및 해당 원시 콘텐츠를 입력으로 사용합니다.

 

2. 메모리 내 문서 저장소(store)를 초기화하고 지정된 벡터 저장소(vectorstore)를 사용하여 다중 벡터 검색기(retriever)를 설정합니다. id_key 매개변수는 검색기 내에서 문서를 식별하는 데 사용되는 키를 결정합니다.

 

3. 함수 내부에는 벡터 저장소와 문서 저장소 모두에 문서를 추가하기 위한 도우미 함수 add_documents가 정의되어 있습니다. 각 문서에 대해 고유한 UUID를 생성하고 요약이 포함된 문서 개체를 페이지 콘텐츠로 생성하여 벡터 저장소에 추가합니다. 또한 UUID를 키로 사용하여 원시 문서 내용을 문서 저장소에 추가합니다.

 

4. 코드는 해당 유형의 문서를 검색기에 추가하기 전에 각 유형의 요약이 비어 있지 않은지 확인합니다.

 

5. OpenAI 임베딩 기능이 포함된 Chroma 벡터 저장소를 사용하여 벡터 저장소(vectorstore)를 초기화합니다.

 

6. create_multi_Vector_retriever 함수를 사용하면 텍스트, 테이블 및 이미지에 대한 벡터 저장소와 요약/컨텐츠를 제공하여 다중 벡터 검색기(retriever_multi_Vector_img)가 생성됩니다.

 

import io
import re

from IPython.display import HTML, display
from langchain_core.runnables import RunnableLambda, RunnablePassthrough
from PIL import Image


def plt_img_base64(img_base64):
    """Disply base64 encoded string as image"""
    # Create an HTML img tag with the base64 string as the source
    image_html = f'<img src="data:image/jpeg;base64,{img_base64}" />'
    # Display the image by rendering the HTML
    display(HTML(image_html))


def looks_like_base64(sb):
    """Check if the string looks like base64"""
    return re.match("^[A-Za-z0-9+/]+[=]{0,2}$", sb) is not None


def is_image_data(b64data):
    """
    Check if the base64 data is an image by looking at the start of the data
    """
    image_signatures = {
        b"\xFF\xD8\xFF": "jpg",
        b"\x89\x50\x4E\x47\x0D\x0A\x1A\x0A": "png",
        b"\x47\x49\x46\x38": "gif",
        b"\x52\x49\x46\x46": "webp",
    }
    try:
        header = base64.b64decode(b64data)[:8]  # Decode and get the first 8 bytes
        for sig, format in image_signatures.items():
            if header.startswith(sig):
                return True
        return False
    except Exception:
        return False


def resize_base64_image(base64_string, size=(128, 128)):
    """
    Resize an image encoded as a Base64 string
    """
    # Decode the Base64 string
    img_data = base64.b64decode(base64_string)
    img = Image.open(io.BytesIO(img_data))

    # Resize the image
    resized_img = img.resize(size, Image.LANCZOS)

    # Save the resized image to a bytes buffer
    buffered = io.BytesIO()
    resized_img.save(buffered, format=img.format)

    # Encode the resized image to Base64
    return base64.b64encode(buffered.getvalue()).decode("utf-8")


def split_image_text_types(docs):
    """
    Split base64-encoded images and texts
    """
    b64_images = []
    texts = []
    for doc in docs:
        # Check if the document is of type Document and extract page_content if so
        if isinstance(doc, Document):
            doc = doc.page_content
        if looks_like_base64(doc) and is_image_data(doc):
            doc = resize_base64_image(doc, size=(1300, 600))
            b64_images.append(doc)
        else:
            texts.append(doc)
    return {"images": b64_images, "texts": texts}


def img_prompt_func(data_dict):
    """
    Join the context into a single string
    """
    formatted_texts = "\n".join(data_dict["context"]["texts"])
    messages = []

    # Adding image(s) to the messages if present
    if data_dict["context"]["images"]:
        for image in data_dict["context"]["images"]:
            image_message = {
                "type": "image_url",
                "image_url": {"url": f"data:image/jpeg;base64,{image}"},
            }
            messages.append(image_message)

    # Adding the text for analysis
    text_message = {
        "type": "text",
        "text": (
            "You are a deep learning and machine learning specialist.\n"
            "You will be given a mixed of text, tables, and image(s) usually of charts.\n"
            "Use this information to provide quality information related to the user question. \n"
            f"User-provided question: {data_dict['question']}\n\n"
            "Text and / or tables:\n"
            f"{formatted_texts}"
        ),
    }
    messages.append(text_message)
    return [HumanMessage(content=messages)]


def multi_modal_rag_chain(retriever):
    """
    Multi-modal RAG chain
    """

    # Multi-modal LLM
    model = ChatOpenAI(temperature=0, model="gpt-4-vision-preview", max_tokens=1024)

    # RAG pipeline
    chain = (
        {
            "context": retriever | RunnableLambda(split_image_text_types),
            "question": RunnablePassthrough(),
        }
        | RunnableLambda(img_prompt_func)
        | model
        | StrOutputParser()
    )

    return chain


# Create RAG chain
chain_multimodal_rag = multi_modal_rag_chain(retriever_multi_vector_img)

 

1. looks_like_base64 함수는 주어진 문자열이 base64로 인코딩된 문자열과 유사한지 확인합니다.

 

2. is_image_data 함수는 헤더를 검사하여 base64로 인코딩된 문자열이 이미지 데이터를 나타내는지 확인합니다.

 

3. resize_base64_image 함수는 base64로 인코딩된 이미지 문자열을 디코딩하고 이미지 크기를 조정한 후 이를 base64 문자열로 다시 인코딩합니다.

 

4. split_image_text_types 함수는 문서 목록을 내용에 따라 이미지 유형과 텍스트 유형으로 분할합니다. 각 문서에서 이미지와 유사한 base64 문자열을 확인하고 그에 따라 크기를 조정합니다.

 

5. img_prompt_func 함수는 RAG 모델 입력에 적합한 형식으로 사용자가 제공한 질문, 상황별 텍스트 및 이미지를 포함하는 메시지를 구성합니다. 컨텍스트 텍스트의 형식을 지정하고 이미지가 있는 경우 이미지 메시지를 추가합니다.

 

6. multi_modal_rag_chain 함수는 다중 모드 RAG 파이프라인을 구성합니다. 관련 컨텍스트 데이터를 가져오는 검색기, 전처리를 위한 람다 함수, 이미지 프롬프트 함수, GPT-4 Vision 모델 및 출력 파서로 구성됩니다.

 

7. 마지막으로 앞서 생성한 검색기로 multi_modal_rag_chain 함수를 호출하여 RAG 체인(chain_multimodal_rag)을 생성합니다.

 

# Check retrieval
query = "Can you give me a brief description on the document."
docs = retriever_multi_vector_img.get_relevant_documents(query, limit=6)

# We get 4 docs
len(docs)

 

검색 쿼리는 다중 벡터 검색기(retriever_multi_Vector_img)를 사용하여 실행됩니다. 쿼리에서는 문서에 대한 간략한 설명을 요청합니다. 검색기의 get_relevant_documents 메소드는 쿼리를 기반으로 관련 문서를 검색하는 데 사용되며 최대 6개의 문서가 지정됩니다.

 

# Run RAG chain
response = chain_multimodal_rag.invoke(query)
response = response.split('.')

# Print each line in a new line
for line in response:
    print(line)

 

The images you have provided appear to be visualizations of attention patterns from a machine learning model, likely from a neural network that processes natural language, such as a transformer-based model
 These types of visualizations are used to understand how the model is paying attention to different parts of the input text when making predictions or generating text


Each image shows lines connecting words in a sentence or phrase
 The thickness and color intensity of the lines indicate the strength of the attention the model is giving to those connections
 In other words, they show which words the model considers important when interpreting the meaning of a particular word


The first image with red lines shows a sentence that reads "The law will never be perfect, but its application should be just - this is what we are missing in my opinion <EOS>
" The attention patterns are dense, suggesting that the model is considering many different connections between the words


The second image with purple and brown lines shows a sentence that reads "It is in this spirit that a majority of American governments have passed new laws since 2009 making the registration or voting process more difficult <EOS>
" The attention here is focused on the latter part of the sentence, particularly on the words "making the registration or voting process more difficult
"

The third image with purple lines is a less intense version of the first image, showing the same sentence with a different attention pattern, possibly from another layer or a different model


The fourth image with green lines is another visualization of the first sentence, again showing a different pattern of attention, which could be from yet another layer or model


The "<EOS>" token typically signifies "End Of Sentence" in natural language processing, indicating the end of the input text for the model


These visualizations are useful for researchers and engineers to debug and improve the model's understanding of language, as well as to gain insights into how the model makes decisions based on the input text

 

이 코드 조각은 다중 모드 RAG 체인(chain_multimodal_rag)을 호출하여 지정된 쿼리에 대한 응답을 생성합니다. 쿼리는 제공된 컨텍스트와 질문을 기반으로 응답 생성을 트리거하는 체인의 invoke 메서드로 전달됩니다.

 

대화형 에이전트를 위한 Multi-modal RAG의 장점:

1. Enhanced Understanding: 다중 모드를 통합함으로써 Multi-modal RAG 모델은 사용자 쿼리의 뉘앙스와 컨텍스트를 더 잘 파악할 수 있습니다. 이미지의 시각적 단서나 문서의 추가 정보는 보다 관련성이 높고 정확한 응답을 생성하는 데 유용한 컨텍스트를 제공할 수 있습니다.

 

2. Richer Responses: 다양한 양식을 활용할 수 있는 능력을 통해 대화 에이전트는 더욱 유익하고 매력적인 응답을 생성할 수 있습니다. 시각적 설명 제공, 관련 문서 참조, 멀티미디어 콘텐츠 통합 등 Multi-modal RAG는 대화 경험을 풍부하게 할 수 있습니다.

 

3. Improved User Interaction: 다중 모드 상호 작용은 실제 커뮤니케이션을 더욱 밀접하게 모방하여 사용자 경험을 더욱 직관적이고 자연스럽게 만듭니다. 사용자는 텍스트, 이미지 또는 문서의 조합을 사용하여 에이전트와 통신할 수 있으므로 보다 유연하고 표현력이 풍부한 상호 작용이 가능합니다.

 

4. Broader Knowledge Integration: 다중 모드 표현을 활용하면 대화 에이전트가 더 넓은 범위의 지식 소스를 활용할 수 있습니다. 상담원은 텍스트 데이터에만 의존하는 대신 시각적 소스와 문서의 정보를 통합하여 지식 기반을 확장하고 응답 품질을 향상시킬 수 있습니다.

 

과제와 향후 방향:

Multi-modal RAG는 대화형 AI 발전에 큰 가능성을 갖고 있지만 잠재력을 최대한 실현하려면 몇 가지 과제를 해결해야 합니다.

 

1. Data Quality and Diversity: 고품질의 다양한 다중 모드 데이터 세트의 가용성을 보장하는 것은 강력한 모델을 교육하는 데 중요합니다. 이러한 데이터 세트를 수집하고 관리하는 것은 특히 다중 모드 데이터가 부족한 영역에서 중요한 과제를 제기합니다.

 

2. Model Complexity and Scalability: 여러 양식을 단일 모델에 통합하면 복잡성과 계산 요구가 증가합니다. Multi-modal RAG 모델의 확장 가능한 배포를 가능하게 하려면 효율적인 아키텍처와 교육 절차를 개발해야 합니다.

 

3. Ethical and Privacy Concerns: 대화형 에이전트가 다양한 데이터 유형을 처리하는 데 더욱 능숙해짐에 따라 사용자 개인 정보 보호를 보장하고 민감한 정보를 윤리적으로 처리하는 것이 가장 중요해졌습니다. 데이터 익명화 및 동의 관리를 위한 강력한 메커니즘이 필수적입니다.

 

4. Evaluation Metrics and Benchmarks: 다중 모드 대화형 AI 시스템에 대한 적절한 평가 지표와 벤치마크를 설정하는 것은 성능을 정확하게 평가하는 데 필수적입니다. 측정항목은 응답 관련성, 일관성, 다중 양식 통합과 같은 요소를 고려해야 합니다.

 

결론

Multi-modal RAG는 대화형 AI의 진화에서 중요한 진전을 나타내며 보다 몰입적이고 상황에 맞게 풍부한 상호 작용을 생성할 수 있는 잠재력을 제공합니다. 텍스트, 이미지 및 문서를 완벽하게 통합함으로써 Multi-modal RAG 모델은 사용자 쿼리를 보다 효과적으로 이해하고 유익할 뿐만 아니라 매력적인 응답을 생성할 수 있습니다. 과제는 여전히 남아 있지만, 이 분야의 지속적인 연구와 개발은 기계와 인간 사이의 인간과 같은 의사소통의 새로운 지평을 열어줄 가능성을 갖고 있습니다.


참고

https://unstructured-io.github.io/unstructured/core/chunking.html

https://unstructured.io/blog/optimizing-unstructured-data-retrieval

https://unstructured-io.github.io/unstructured/best_practices/table_extraction_pdf.html

https://github.com/SunGajiwala/langchain/blob/master/cookbook/Multi_modal_RAG.ipynb

 

따라하기

https://sungajiwala54.medium.com/unlocking-conversational-ais-potential-a-deep-dive-into-multi-modal-rag-for-large-pdf-f6e48057e08d

https://github.com/dongshik/Multi-Modal-using-RAG/blob/test/Multi_modal_RAG.ipynb

 

 

+ Recent posts