기본 RAG 의 개념 : 기본 RAG (Retrieval Augmented Generation) 는 query 를 입력으로 받아 vector store 로부터 relevant 한 chunk 를 검색해서 가져온 후, 이를 prompt 에 추가해서 최종적인 답변을 출력한다.
사용된 개념
1. Relevance Check : vector store 에서 retrive 해온 chunk 가 relevant 한지 LLM 을 활용해서 검증한다.
2. Hallucination Check : retrieved chunk 를 참고해서 생성한 최종 답변이 hallucination 인지 여부를 LLM 을 활용해서 검증한다.
RAG 를 사용하기 위한 프레임워크로 langchain 을 사용한다. (비슷한 역할을 하는 Llamaindex 라는 프레임워크도 있다.)
목적: 3가지 웹문서를 vector store 로 저장하고, 이에 기반해 사용자 질문에 답변하는 RAG 를 만든다.
import getpass
import os
os.environ["OPENAI_API_KEY"] = "API_KEY 를 입력하세요."
from langchain_openai import ChatOpenAI
# openai의 gpt-4o-mini 모델 사용
llm = ChatOpenAI(model="gpt-4o-mini")
3. 문서를 로드한다.
- langchain 의 WebBaseLoader를 활용하며, beautiful soup 라이브러리를 활용해 html 태그 등을 parsing 해 본문 내용만 가져온다고 이해하면된다.
import bs4
from langchain import hub
from langchain_chroma import Chroma
from langchain_community.document_loaders import WebBaseLoader
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter
urls = [
"https://lilianweng.github.io/posts/2023-06-23-agent/",
"https://lilianweng.github.io/posts/2023-03-15-prompt-engineering/",
"https://lilianweng.github.io/posts/2023-10-25-adv-attack-llm/",
]
# Load, chunk and index the contents of the blog.
loader = WebBaseLoader(
web_paths=urls,
bs_kwargs=dict(
parse_only=bs4.SoupStrainer(
class_=("post-content", "post-title", "post-header")
)
),
)
docs = loader.load()
4. 로드한 문서를 Split 해서 Vector store 로 저장한다.
- chunk size 는 1000 토큰이며, 200의 오버랩을 허용한다. 각 청크간에 약간의 중복을 준다는 의미이다.
- chunk 를 vector 로 저장할 때, embedding 이 필요한데, openai 의 text-embedding-3-small 모델을 사용했다.
- retrieval 의 세팅으로 similarity 를 기준으로 6개의 chunk 를 가져오는 retrieval 객체를 정의한다.
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
splits = text_splitter.split_documents(docs)
vectorstore = Chroma.from_documents(documents=splits, embedding=OpenAIEmbeddings(model="text-embedding-3-small"))
# Retrieve and generate using the relevant snippets of the blog.
retriever = vectorstore.as_retriever(search_type="similarity", search_kwargs={'k':6})
5. user query 를 입력으로 받아 관련도가 높은 chunk 를 retrieve 해온다.
- 가져온 chunk 6개를 1번 chunk : ... 2번 chunk : ... 이런 형식으로 텍스트 형식으로 저장한다.
from langchain_core.output_parsers import JsonOutputParser
from langchain_core.prompts import PromptTemplate
from langchain import hub
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import JsonOutputParser
from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
prompt = hub.pull("rlm/rag-prompt")
user_query = "What is agent memory?"
retrieved_docs = retriever.invoke("what is agent memory?")
retrieved_docs_text = ""
for i in range(0,6) :
doc_content = retrieved_docs[i].page_content
retrieved_docs_text += f'{i+1}번 chunk: {doc_content}\n'
6. 목적에 맞는 최종 prompt 를 작성한다.
- relevance check 와 hallucination check 를 하여 기본 RAG 를 좀 더 개선하는 것이 목적이므로, 이에 대한 로직을 추가한 프롬프트를 작성한다. 전체적인 답변 생성 로직과 함께 필요한 정보 - 유저 query 와 retrieved chunk 를 제공해주어야한다.
query = {"question": {f"""
너는 유저로부터 query 를 입력 받아서 최종적인 답변을 해주는 시스템이야.
그런데, retrieval 된 결과를 본 후에, relevance 가 있는 retrieved chunk 만을 참고해서 최종적인 답변을 해줄거야.
아래 step 대로 수행한 후에 최종적인 답변을 출력해.
Step1) retrieved chunk 를 보고 관련이 있으면 각각의 청크 번호별로 relevance: yes 관련이 없으면 relevance: no 의 형식으로 json 방식으로 출력해.\n
Step2) 만약 모든 chunk 가 relevance 가 no 인 경우에, relevant chunk 를 찾을 수 없었습니다. 라는 메시지와 함께 프로그램을 종료해.
Step3) 만약 하나 이상의 chunk 가 relevance 가 yes 인 경우에, 그 chunk들만 참고해서 답변을 생성해.
Step4) 최종 답변에 hallucination 이 있었는지를 평가하고 만약, 있었다면 hallucination : yes 라고 출력해. 없다면 hallucination : no 라고 출력해.
Step5) 만약 hallucination : no 인 경우에, Step3로 돌아가서 답변을 다시 생성해. 이 과정은 딱 1번만 실행해 무한루프가 돌지 않도록.
Step6) 지금까지의 정보를 종합해서 최종적인 답변을 생성해
답변은 각 스텝별로 상세하게 출력해
아래는 user query 와 retrieved chunk 에 대한 정보야.
query : {user_query}\n
retrieved chunks: {retrieved_docs_text}"""}}
7. Prompt Template 을 기반으로 RAG Chain 을 호출해 최종 답변을 json 형식으로 출력한다.
- prompt template 은 프롬프트를 구조화된 형식으로 작성할 수 있게 도와주는 클래스이다.
- rag chain 은 query-> prompt -> llm -> output 파이프라인을 하나의 함수로 실행할 수 있도록 해준다.
json\n{\n "step1": {\n "1": "relevance: yes",\n "2": "relevance: yes",\n "3": "relevance: yes",\n "4": "relevance: yes",\n "5": "relevance: no",\n "6": "relevance: no"\n },\n "step2": "All retrieved chunks have relevance.",\n "step3": "The relevant chunks provide information about agent memory, which consists of both long-term and short-term memory. Agent memory is a long-term memory module that records agents\' experiences in natural language. Observations can trigger new statements, and the retrieval model assists in informing the agent’s behavior based on relevance, recency, and importance. Additionally, the reflection mechanism synthesizes these memories into higher-level inferences over time.",\n "step4": "hallucination: no",\n "step5": "Since hallucination is no, I will generate the answer again.",\n "step6": {\n "final_answer": "Agent memory refers to a long-term memory module that captures a comprehensive list of an agent\'s experiences in natural language, which can be used to inform the agent\'s behavior. It includes short-term aspects, such as in-context learning, as well as long-term memory that retains information over extended periods. The retrieval model helps prioritize memories based on relevance, recency, and importance, while the reflection mechanism synthesizes past events into higher-level insights that guide future behavior."\n }\n}\n
아래 코드는 일별로 유저수와 그 유저의 피쳐 a,b,c 에 대해 각각 평균과 중위수를 구하는 코드이다. 이 코드는 상당히 시간이 오래 걸린다.
select
date_id,
count(distinct user_id) as user_cnt,
avg(a) as avg_a,
avg(b) as avg_b,
avg(c) as avg_c,
percentile_approx(a, 0.5) as med_a,
percentile_approx(b, 0.5) as med_b,
percentile_approx(c, 0.5) as med_b
from table
group by date_id
그런데, user_cnt 와 평균을 구하는 코드를 제외한 아래 쿼리는 빠르게 실행된다. 왜 그럴까?
select
date_id,
percentile_approx(a, 0.5) as med_a,
percentile_approx(b, 0.5) as med_b,
percentile_approx(c, 0.5) as med_b
from table
group by date_id
챗 GPT 를 활용해 답변을 생성해보니 아래와 같다고 한다.
유저수를 count하는 연산과 평균을 구하는 연산이 맵리듀스 분산 처리시(Big Data 환경을 가정) 각 노드에서 개별적으로 이루어져서 빠른 처리가 가능하지만, 중앙값을 구하는 percentile_approx 연산은 전체 데이터를 한 노드에서 모아서 처리해야 하기 때문에 상대적으로 시간이 많이 소요됩니다.
하지만, 여러 컬럼의 중앙값을 동시에 구하는 쿼리에서는 중앙값을 구하는 작업이 모든 컬럼에 대해 동시에 이루어지기 때문에 시간이 대폭 줄어듭니다.
즉, count와 avg는 분산처리가 가능하여 각각의 연산이 독립적이지만 percentile_approx는 분산처리가 어려워서 전체 데이터에 대한 연산이 필요하여 시간이 오래 걸린 것입니다. 두번째 쿼리는 percentile_approx만 있기 때문에 동시에 처리될 수 있어 속도가 빠른 것입니다.
확인하기 위해, 각각의 연산을 따로 실행하는 쿼리를 만들어 시간을 체크해보면 더 정확한 비교가 가능할 것입니다.
결론
- hive sql 에서 percentile_approx 는 분산처리가 어렵고 전체 데이터에 대한 연산이 필요하기 때문에 시간이 오래 걸린다.
- hive sql 에서 percentile_approx 를 활용해 중위수를 구할 때에는 다른 집계는 하지 말고 중위수만 구하자. 그럼 조금 더 빠르다.
아래와 같은 오류 또는 test_env 를 찾을 수 없습니다. 등, Rmd 파일을 knitr 을 통해 변환시킬 때 에러가 발생했다.
에러 메시지 예시
|................................ | 50%
ordinary text without R code
|.................................................................| 100%
processing file: Preview-b0c112a265.Rmd
label: unnamed-chunk-1
Quitting from lines 16-26 (Preview-b0c112a265.Rmd)
Error in file(file, "rt") : cannot open the connection
Calls: <Anonymous> ... withVisible -> eval -> eval -> read.csv -> read.table -> file
Execution halted
해결: [Tool] - [Global Options] - [R Markdown] - Evaluate Chunks in Directory 를 current 로 변경
위와 같이 세팅을 변경하자 문제가 해결되었다. 위 문제로 인해 마크다운 문서를 작성할 때 Rstudio server 가 아니라 로컬에서 작업을 항상 했었는데 불편함이 존재했었다. 위 방법으로 깔끔하게 해결되었고, 앞으로 마크다운 문서 작성도 R studio server 에서 하면 될듯하다.
R markdown 형식을 html 로 변환해 호스팅하는 패키지로 blogdown 이 유명했는데 최근 많은 유저들이 distill 로 많이 갈아타고 있는듯하다. blogdown 의 경우 hugo 를 기본으로 블로그 템플릿이 만들어지는데 hugo 보다 distill 의 기본 포맷이 조금 더 학술적인 느낌이기 때문에 개인적으로 distill 이 R 관련 포스팅에 좀 더 적합한 느낌으로 보인다.
The Distillery: Distill 매뉴얼은 조금 드라이하게 작성 되어 있는듯하다. distill 사용을 좀 더 잘하기 위한 tip 등을 공유하는 사이트로 The Distillery 가 있다. (https://distillery.rbind.io/tips_and_tricks) 여기에서는 Distill 을 사용할 때의 tips and tricks 와 showcase 를 공유한다. showcase 를 보면 다른 유저들이 distill 을 이용해서 블로그를 어떻게 운영하고 있는지를 볼 수 있어 개인 블로그를 만드는데 참고가 될 것이다.
간단하게 Distill 과 Github pages 를 통해 10분 이내로 블로그를 만들어보자.
물론 github 계정, git 설치, R 설치는 기본적으로 필요하다.
Distill 설치
install.packages('distill')
Distill Blog Project 생성
위와 같이 블로그를 생성하면 홈폴더 바로 아래에 있는 하위 폴더에 "_site" 라는 폴더가 있는데 여기에 웹사이트 최초 시작지점인 index.html 파일이 존재한다. 이렇게 github pages 로 push 하면 [githubID].github.io/_site 가 블로그의 주소가 된다. 만약 [githubId].github.io 를 주소로 블로그를 호스팅하고 싶다면, _site 에 위치한 파일들을 모두 home 폴더로 옮겨준다. 그리고 홈폴더 바로 아래에 있는 _site.yaml 파일의 output_dir 을 "." 으로 설정한다.
본인의 github 에 [id].github.io 라는 이름의 레포지토리를 만들고 여기에 만든 코드를 push 를 해주면 블로그가 잘 생성된 것을 볼 수 있다. github pages 로 푸시하는 과정은 아래와 같다.
cd [home] # 생성한 distill 프로젝트의 홈폴더로 이동한다.
git init
git add --all
git commit -m 'first commit'
git remote add origin https://github.com/[id]/[id].github.io
git push origin master
아래와 같은 형태의 기본 Distill 템플릿의 블로그가 생성되었다.
* 또는 output_dir 을 docs 로 설정한 후, github pages 설정에서 source 폴더를 docs 폴더로 설정하는 것을 추천한다.
포스트 조금 수정해보기
1) 포스트에 카테고리 붙이기
기본적인 블로그에는 오른쪽의 CATEGORIES 메뉴가 없을 것이다. 카테고리를 만드는 방법은 단순히 포스트에 다가 category tag 를 붙이면된다. 카테고리를 직접적으로 지정할 필요없이 포스트에 붙어 있는 태그를 통해 전체 카테고리가 재구성된다.
---
title: "Welcome to My Blog"
categories:
- Category1
- Category2
- Category3
description: |
Welcome to our new blog, My Blog. We hope you enjoy
reading what we have to say!
author:
- name: Nora Jones
url: https://example.com/norajones
affiliation: Spacely Sprockets
affiliation_url: https://example.com/spacelysprokets
date: 08-23-2024
output:
distill::distill_article:
self_contained: false
---
2) rmd 를 html 형식으로 변환하기
- 카테고리를 붙이는 등 rmd 파일을 수정했다면 이를 html 로 변환해줄 필요가 있다.
- 기본적으로 rstudio 에서 build - Install and Restart 를 누르면 빌드된다.
- 다만 build 를 통해서는 각 포스트가 html 로 변환되지는 않는다. 포스트를 변환하기 위해서는 각 rmd 파일에 대해 knitr 을 실행해서 rmd 파일을 html 파일로 변환해주면 된다.
Knit 를 통해 rmd 파일을 html 파일로 변환함으로써 github pages 를 통해 호스팅할 수 있다.
R 에서 ggplot 을 통해 그래프를 그릴 때 불편했던 점이 텍스트 레이블을 차트에 표시하기 어려웠던 점이다. 엑셀로 그래프를 그리는 경우 레이블 옵션을 설정한 뒤 이를 마우스 드래그를 통해서 조정할 수 있으나, ggplot 에서는 hjust, vjust 를 통해 한땀한땀 레이블을 조정하곤했다.
혹시나 레이블의 위치를 자동으로 바꿔주는 패키지가 있나 살펴보다가 ggrepel 이라는 패키지가 있다는 것을 알았다. 사용법은 매우 쉽다. 만드려고한 ggplot 에다가 + geom_text_repel() 만 해주면 된다.
텍스트간의 겹치는 것을 조정해주기도 하지만, line 이나 point 와 같은 그래프의 요소와 텍스트가 겹치는 것을 알아서 조정해주기도 한다. 아래의 line chart 를 보면 point 와 겹치지 않게 text 가 자동으로 위치가 조정된 것을 볼 수 있다.
quantile_output 이라는 폴더 아래에 6월 1일~6월 30일 사이의 30개의 csv 파일이 존재한다. 각 파일들은 같은 형식이며, 각기 다른 날짜에 집계됐다는 점만 다르다. 이 경우에 1) Sys.glob 을 이용해 해당 파일들의 경로를 벡터 형태로 만든 후에 2) lapply 를 통해 각 파일들을 읽어 list of dataframes 를 만들고, 3) 마지막으로 bind_rows 를 통해 dataframe 으로 만들어주면 된다.
분석을 하다보면 두 집합이 얼마나 교차하는가? 를 이야기하고 싶을 때가 있다. A 그룹 유저는 B 그룹 유저와 N% 겹치고, B 그룹 유저는 A 그룹 유저와 M% 겹칩니다! 라고 말할 수 있다. 하지만 대량으로 이러한 교차성에 대한 값을 구해서 비교해 본다고 하자. 좀 더 심플하고 요약된 지표가 있다면 비교가 용이할 것이다. 교차성에 대한 정보를 0~1 사이의 값으로 나타내는 지표에는 어떤 것들이 있을까? 그리고 그 지표들 간에는 어떤 차이가 있을까?
우선, 벤다이어그램으로 표현한 데이터는 아래와 같이 binary vector 로도 표현할 수 있다. 예를 들어, 어떤 유저들이 A 서비스를 사용하는지 B 서비스를 사용하는지 여부를 binary vector 로 아래와 같이 나타낼 수 있다.
Sample
A서비스사용
B서비스사용
1
1
1
2
1
0
3
0
1
4
1
0
5
1
0
유사도란 A, B 두 벡터가 얼마나 유사한지를 보는 것으로 이해할 수 있다. 또는, 벤다이어그램에서 겹치는 부분이 얼마나 되는지를 의미하는 지표라고 해석할 수 있다.
1. Jaccard Index
Jaccard index 는 가장 기본적으로 생각할 수 있는 유사도 지표이다. 이것은 벤다이어그램에서 교집합 크기를 합집합 크기로 나눈 것으로 정의된다. 벤다이어그램에서 교차되는 부분의 면적을 전체 원의 면적으로 나눈 것이다.
$$ J(A,B) = \frac{{|A \cap B|}}{{|A \cup B|}} $$
$$ J(A,B) = 100 / 1300 = 0.08 $$
Jaccard index 전통적으로 두 문서의 유사도를 비교할 때 쓰이기도 한다. A 문서와 B 문서의 유사도를 비교할 때, 두 문서에 등장하는 단어들을 하나의 샘플로해서 A,B 문서에 속했는지 여부를 이진 벡터로 만들 수 있을 것이다. 최종적으로 A문서와 B문서의 이진벡터를 만들 수 있고, 이를 통해 Jaccard index 를 구할 수 있다.
2. Dice coefficient
Dice coefficient는 두 집합의 교집합 크기의 두 배를 두 집합 크기의 합으로 나눈 값이다.
$$ D(A,B) = \frac{{2|A \cap B|}}{{|A| + |B|}} $$
$$ D(A,B) = \frac{100*2}{1000+400} = 0.14$$
3. Kulczynski similarity index
A 의 크기가 1만, B의 크기가 10, 그리고 A교집합B가 9라고 하자. B의 입장에서는 90%가 A와의 교집합인데 Jaccard index 나 Dice coefficient 는 낮게 계산된다. Kulczynski similarity 는 A 와 B 각각에서 교집합의 비율을 평균낸 값이기 때문에, B 입장에서 90%인 교집합의 비율이 동등하게 지표에 반영된다. Kulczynski similarity 는 두 집합의 크기 차이가 클 때, 이를 보정하는 지표로 볼 수 있다.
즉, Kulczynski similarity 두 데이터 셋 간의 크기 차이가 결과에 미치는 영향을 감소시킨다. 반면, Jaccard index 나 Dice coefficient 의 경우, A,B의 크기의 차이가 결과에 영향을 미친다.
4. Cosine similarity (코사인 유사도)
Cosine similarity 는 두 벡터의 코사인 값을 통해 유사도를 구하는 개념이다. 코사인 유사도는 이진 벡터가 아닌 데이터에서도 광범위 하게 사용되는 measure 이다. 예를 들어, 자연어 처리에서 두 워드 임베딩 값의 유사도를 볼 때 쓰이기도 한다. 벤다이어그램에서는 두 벡터가 이진 벡터이기 때문에 두 벡터의 내적은 (1,1) 인 행의 숫자, 즉 교집합의 크기를 의미한다. 또한, 각 벡터의 크기는 집합의 크기의 제곱근이다.
어떠한 두 그룹의 교차되는 부분의 규모를 표현할 때, 벤다이어그램은 매우 효과적인 방법입니다. 벤다이어그램을 그리기 위해 파워포인트, Keynote 같은 프로그램을 이용할 수 있습니다. 하지만, 실제 수치를 반영해서 원의 크기를 조정하고 싶을 수 있습니다. 이 때, R 의 VennDiagram 패키지를 이용할 수 있습니다.
코드는 아래와 같습니다. draw.pairwise.venn 함수에 area1, area2, cross.area 에 해당하는 값을 넘겨줍니다. 이 때 주의할 점은 area1, area2 에서는 교차되는 부분을 포함하는 값을 넣어주어야 합니다.
VennDiagram 패키지를 통한 벤다이어 그램 그리기
2개 집합 벤다이어그램
area1 : A
area2 : B
cross.area : A∩B
library(VennDiagram)
A <- 1000
B <- 400
C <- 100
# 벤다이어그램 원 내부 수치 있도록 변경
# scaled = FALSE 로 지정하면, 실제 수치를 고려하지 않은 벤다이어그램을 그려줌
grid.newpage()
v <- draw.pairwise.venn(area1 = A, area2 = B, cross.area = C,
fill = c("light blue", "pink"),
alpha = rep(0.5, 2),
fontfamily='Kakao Regular', scaled=TRUE)
grid.draw(v)
# cex = 0 옵션을 통해 벤다이어그램 원 내부 수치 제거
grid.newpage()
v <- draw.pairwise.venn(area1 = A, area2 = B, cross.area = C,
fill = c("light blue", "pink"),
alpha = rep(0.5, 2),
fontfamily='Kakao Regular', cex=0, scaled=TRUE)
grid.draw(v)
1. Koch's Postulates: 특정 미생물이 특정 질병의 원인임을 증명하기 위한 4가지 기준
질병이 발생한 모든 사례에서 미생물이 발견되어야 한다.
해당 미생물을 순수 배양해야 한다. 특정 질병의 원인 미생물이 어떤 것인지 정확히 확인하기 위해서는 다른 미생물이 섞이지 않은 상태에서 해당 미생물만을 배양해야 한다.
배양한 미생물을 건강한 숙주에 접종하여 동일한 질병을 유발해야 한다.
실험적으로 감염된 숙주에서 동일한 미생물을 재분리해야 한다.
질병인 경우 미생물 발견. 순수 배양 한뒤에, 건강한 사람에게 질병 유발하는지 확인. 질병 감염된 사람한테서 그 미생물이 또 발견되는지 확인. 이러면 미생물이 질병의 원인이라고 볼 수 있다.
2. Contagion(컨테이전)은 전염성 질병이 사람 사이에 전파되는 현상을 의미한다. 이 용어는 질병의 확산과 전파 과정을 설명하는 데 사용된다.
3. 만약, 환경으로부터 감염되는 질병이라고하면 이는 non-contagious 이다. 예를 들어, 라지오넬라병이나, 곰팡이(fungi) 에 의한 감염은 환경으로부터 감염되는 것이기 때문에 contagious 가 아니다.
4. Infectious Respiratory Aerosol (감염성 호흡기 에어로졸) 은 호흡기 질환을 일으킬 수 있는 병원체(바이러스, 박테리아 등)를 포함한 미세한 액체 또는 고체 입자를 의미한다.
- Droplet transmission : 비말 전파 : 액체로 부터 직접적으로 접촉해서 감염되는 경우. 비말이 빠르게 지면으로 침강하기 때문에 이로 인한 전달은 빠른 시간내에 이루어짐. 비교적 큰 입자 크기 (5마이크로미터 이상)
- Airborne transmission (droplet nuclei transmission) : 비말핵 전파 : 집적 접촉이 아니라, 비말핵이 공기중을 떠돌아다니다가 감염. 감염자와 직접적으로 같이 있지 않더라도, 감염자가 머문 공간의 공기에 접촉해서 감염될 수 있음. 비교적 작은 입자 크기 (5마이크로미터 이하)
5. Obligate Airborne Transmission(필수 공기 전파) 정의: 병원체가 주로 공기를 통해서만 전파되는 경우를 말한다. 이러한 병원체는 공기 중에 떠 있는 미세한 에어로졸 입자를 통해 전파되며, 이는 감염된 사람과 직접 접촉하지 않고도 쉽게 전파될 수 있다 (pulmonary TB).
6. Preferentially Airborne Transmission(선호 공기 전파) 정의: 병원체가 여러 전파 경로 중에서 공기 전파를 선호하지만, 반드시 공기 전파만으로 전파되지는 않는 경우를 말한다. 이러한 병원체는 공기 전파 외에도 비말 접촉, 표면 접촉 등을 통해 전파될 수 있다 (chicken pox).
7. Airborne viral infections 의 예시 (공기 전파 바이러스 감염)
- 일반 감기
- 인플루엔자
- epidemics 에 의한 분류: pandemic vs. seasonal
- host 에 따른 분류 : non-zoonotic vs. zoonotic - 주의사항: 일부 동물병의 경우 드물게 사람을 감염시킬 수 있다.
- 코로나바이러스
8. Airborne bacterial infections 예시 (공기 전파 박테리아 감염)
- Mycobacterium tuberculosis 균에 의한 Pulmonary tuberculosis (TB, 결핵) 감염
- Legionella 균에 의한 Legionallosis, Pontiac fever 발생
- TB 는 사람간 전파됨 (contagious)
- 레지오넬라는 사람간 전파안됨 (non-contagious)
- Anthrax (탄저병) : 탄저균(Bacillus anthracis) 감염에 의해 발생하는 급성 감염질환. 감염된 동물에 의해 사람에게 감염됨 (non-contagious)
9.Fungal infection (mycosis) : 곰팡이나 효모 같은 진균류에 의해 발생하는 감염
- pathogenic fungi 를 포함하고 있는 공기를 흡입하여 발생함
10. Allergy : 면역 반응에 의한 Hypersensitivity reaction 이다. 알러지를 일으키는 물질을 Allergen 이라고함.
- Allergic asthma : Cough and wheezing
- Allergic rhinitis : Running nose
- Allergic bronchopulmonary mycoses : Fungal allergy, infection in lungs
... 등등 Allergy 에는 다양한 분류와 증상이 존재한다. 감염과 allergy 는 다르다. 곰팡이는 감염을 일으킬 수도 있고, 알러지를 일으킬 수도 있고, 둘 다 일으킬 수도 있다.
11. Thunderstorm asthma : Thunderstorm Asthma(천둥번개 천식) 는 천둥번개를 동반한 폭풍우가 발생한 후 특정 기상 조건에서 많은 사람들이 급성 천식 발작을 일으키는 현상을 말한다. 이 현상은 주로 봄과 여름철에 발생하며, 특히 호주와 같은 일부 지역에서 잘 알려져 있다.
원인: 폭풍우가 발생하기 전에 공기 중에 높은 농도의 꽃가루와 곰팡이 포자 (plant pollen, fungal spores) 가 존재할 수 있다. 이들 알레르겐은 폭풍우의 강한 바람과 번개에 의해 작은 입자로 분해되며, 비와 함께 대기 중에 분산된다.
12. 다른 알러지 발생 요인
- House dust mite (집먼지 진드기) 알러지 : 99% 가 HDM 의 feces 에 의해 발생
- Cockroaches : saliva, feces, shedding skin 등에 의해 발생
- Dog : major source - saliva, dander, urine
- Cat : saliva, fur, urine
- Bird : excrements, feather dust (깃털에 존재하는 1마이크로미터 이하의 매우 작은 물질이 있음)
13. Bioactive compounds 에 의한 건강 영향
- endotoxins : gran-negative bacteria 에서 나오는 독성
- mycotoxins : fungi 로 부터 나오는 독성 (대사 산물임)
생명체로부터 나오는 독성물질을 의미함
14. 어린 시절 개와 같이 사는 등 endotoxins 과 같은 알러지, 질병 유발 요인에 노출되는 것이 면역체계 발달에 좋은 영향을 줄 것이라는 가설이 존재함
15. HEPA filter (High Efficiency Particulate Air Filter) : 필터가 가장 포집하기 어려운 입자가 대략 0.3마이크로미터 입자인데, 이는 입자가 크거나 작으면 각기 다른 포집 방법에 의해 잘 포집되는데, 애매한 크기는 각기 다른 포집방법에서 잘 포집되지 않기 때문이다. HEPA 필터는 0.3 마이크로미터 입자의 99.7% 이상을 포집할 수 있어야한다.
16. 공기청정기의 성능: CADR (Clean Air Delivery Rate)
V = volume of the test chamber (ft3)
k_e = decay rate mearsured with the air purifier (min-1)
k_n = natural decay rate measured without the air purifier (min-1)
$$ CADR = V (k_e - k_n) $$
16. HVAC System : Heating, Ventilation, and Air Conditioning (HVAC) system : 온도 조절, 실내 공기질을 좋게 유지시켜주는 시스템
17. UVGI (UltraViolet Germicidal Irradiation) : UVGI는 자외선의 살균 특성을 이용하여 공기, 물, 그리고 표면의 미생물을 불활성화시키는 방법
- In-duct UVGI : HVAC system 안에 설치해서 흐르는 공기를 자외선을 이용해 살균함
- Upper room UVGI: 방 상단에 설치해서 실내 공기를 살균함
- 자외선중에 UV-C 라는 자외선이 사용된다.
18. Greenhouse gases (GHGs) : 대기의 열을 잡아놓는 기능을 하는 가스
19. The Keeling Curve : 킬링 곡선은 지구 대기의 이산화탄소(CO₂) 농도를 시간에 따라 나타낸 그래프다. 이 곡선은 1958년에 하와이의 마우나로아 관측소에서 대기 중 CO₂를 체계적으로 측정하기 시작한 찰스 데이비드 킬링(Charles David Keeling)의 이름을 따서 명명되었다. 이 그래프는 인간 활동이 지구 기후에 미치는 영향을 보여주는 중요한 지표 중 하나다.
20.Radiative forcing : 복사 강제력(radiative forcing)은 지구의 에너지 균형에 영향을 미치는 요인을 측정하는 개념이다. 이는 지구 대기로 들어오는 태양 복사 에너지와 지구에서 방출되는 적외선 복사 에너지 간의 균형 변화를 나타낸다. 복사 강제력은 기후 변화를 이해하고 예측하는 데 중요한 역할을 한다.
위 그림에서 Radiative force 가 +인 요인은 지구 온도를 상승시키는 요인. -인 요인은 지구 온도를 하락시키는 요인임
21. Aerosol-cloud-radiation interactions
에어로졸은 태양 복사 및 지구 복사를 직접적으로 흡수하거나 반사하여 지구의 복사 균형에 영향을 미친다:
직접 효과 (Direct Effect):
에어로졸 입자는 태양 복사를 반사하여 지표면으로 도달하는 태양 에너지를 감소시킨다. 예를 들어, 황산염 에어로졸은 태양 복사를 반사하여 냉각 효과를 나타낸다.
일부 에어로졸은 태양 복사를 흡수하여 대기를 가열한다. 예를 들어, 검댕(black carbon)은 태양 복사를 흡수하여 온난화 효과를 나타낸다.
간접 효과 (Indirect Effect):
에어로졸은 구름의 반사율과 수명을 변화시켜 지구 복사 균형에 간접적으로 영향을 미친다. 예를 들어, 에어로졸이 많은 구름은 반사율이 높아져 냉각 효과를 나타낼 수 있다.
하지만 실제로 지구 온도에 대한 aerosol 의 영향을 정확하게 측정하기 어렵다. 많은 부분이 불확실하게 남아 있음.
22. 지구 온난화가 bioaerosol 에 미치는 영향 : Global warming 인 아래와 같은 경로로 bioaerosol 에 영향을 미친다.
- 이산화탄소 상승 -> 기온 상승 -> 식물 성장 증가, 꽃가루 증가
- 이상 기후 증가 -> 천둥 천식
- 해수면 상승 -> 범람 증가 -> 쓰나미가 일어난 이후 대기 오염으로 인해 천식이 증가하는 사례 (Katrina cough)
23. Bioaerosol 이 세계 기후에 미치는 영향 : 구름 형성, 복사 강제력 (열의 흡수나 반사를 통해 지구 온도를 변화시키는 힘)
- 구름형성: 에어로졸은 대기에서 cloud condensation nuclei (CCN) 또는 ice nuclei (IN) 처럼 작용할 수 있음
- 구름 응결핵(CCN)은 수증기가 응결하여 구름 방울을 형성하도록 도와주는 입자다. 에어로졸에 수증기가 붙어 액체가 되면서 성장하는 방식으로, 수증기상태의 물이 액체 상태로 변경하도록 도와줌.
- 얼음핵(IN)은 대기 중의 수증기가 얼음 결정으로 변하는 과정을 촉진하는 입자다.
24. Bioprecipitation : 대기 중 특정 미생물, 특히 박테리아가 구름 형성과 강수(비, 눈) 과정에서 중요한 역할을 한다. 그리고 비에 섞여 있다.
1. PCR 발명자는 폴란드 생화학자 Kary Mullis 이다. (PCR = polymerase chain reaction : DNA 의 특정 부분을 증폭시키는 기술)
2. 찰스 다윈은 비글호에서 케이프 베르데 제도 근처에서 먼지를 수집했는데, 이를 사하라 먼지라고 한다. 이는 먼지가 매우 넓은 지역에 걸쳐 이동할 수 있다는 것을 의미하고, 먼지가 대기 중에서 얼마나 멀리 퍼질 수 있는지를 보여주는 중요한 사례이다.
3. 코흐는 1880년대에 감자 조각과 이후에는 한천을 이용한 고체 배지 (solid culture media) 를 개발하여 세균을 배양하는 방법을 개선했다. 이는 세균학 연구에서 중요한 진전을 이뤄냈으며, 다양한 세균을 분리하고 연구하는 데 큰 기여를 했다.
4. 한천 배지(Agar Media)와 젤라틴 배지(Gelatin Media)는 미생물 배양에 사용되는 두 가지 주요 고체 배지이다. 둘 중, 한천 배지가 일반적으로 더 많이 사용된다.
5. LIF : Laser Induced Fluorescence(레이저 유도 형광) : 레이저를 이용해 입자나 분자에서 형광을 유도하여 공기 중의 생물학적 입자나 물질을 검출하고 분석하는 기술
6. MALDI는 Matrix-Assisted Laser Desorption/Ionization의 약자이다. 이는 질량 분석법에서 사용되는 이온화 기술 중 하나로, 주로 단백질, 펩타이드, 당, 폴리머 등의 큰 분자들을 분석하는 데 사용된다. 최종적으로 질량 대 전하 비율(m/z) 을 통해 어떤 입자인지를 특정할 수 있다.
7. TEM은 Transmission Electron Microscopy(투과 전자 현미경)의 약자이다. TEM은 전자 현미경의 한 종류로, 고해상도의 이미지와 세부 구조를 관찰하는 데 사용된다.
8. 인플루엔자 A 형: H1N1 ~ H18N11 까지 다양한 형으로 존재함 (신종플루, 스페인독감)
인플루엔자 B 형: 두 가지 주요 라인(B/Victoria와 B/Yamagata)으로 나뉨
9. Legionella (레지오넬라)는 주로 물 환경에서 서식하는 박테리아로, 레지오넬라 폐렴(Legionnaires' disease)과 폰티악 열(Pontiac fever)을 일으킬 수 있다. 레지오넬라 감염은 일반적으로 사람 간 전파(person-to-person transmission)가 아닌 환경적 노출을 통해 발생한다.
10. 생명체의 분류 (domain of life) : 생명체는 Eukaryote(진핵생물)와 Prokaryote(원핵생물)로 구분되고, Prokaryote 는 Archaea(고세균)와 Bacteria(진정세균) 으로 분류됨
11. terminal settling velocity : 종단속도 = 공기저항에 의한 힘과 중력이 평형을 이루어 속도가 일정하게 하강하는 상태를 의미함.
relaxiation time 은 종단속도에 이르기까지 걸리는 시간을 반영하는 지표인데 (실제로 걸리는 시간은 아니다.) 종단속도를 중력가속도 g로 나누어 계산함
12. 필터의 3가지 원리 : Inertia, Interception, diffusion (Brownian motion)
13. 공기저항은 하강중인 입장의 직경, 모양, 속도에 의존적이다.
14. real-time bioaerosol monitor 에서 모니터링하는 biofluorophores 의 대표적인 예는 NADH 이다.
역할: NADH는 생물체의 세포 내에서 중요한 역할을 하는 보조 인자로, 주로 세포 호흡과 에너지 대사 과정에서 전자 운반체로 작용
형광 특성: NADH는 자외선(UV) 빛을 흡수하고 청색 형광을 방출하는 특성을 가지고 있다.
16. Mycobacterium tuberculosis 의 generatio time 은 1200분이다 .만약, 하나의 세포가 3일 동안 배양되었을 때, cell 의 개수는?
$$ N=N_02^n $$
3일 = 60 * 24 * 3 = 4320m
$$ 1*2^{4320/1200} = 12.12 $$
17. ELISA(Enzyme-Linked Immunosorbent Assay)는 특정 단백질, 항원, 항체 등을 검출하고 정량화하는 데 사용. 효소가 결합된 항체를 이용해 검출하는 방법
18. endotoxin 을 검출하기 위한 LAL (리무스 아메보사이트 리세이트, Limulus Amebocyte Lysate) 분석법은 엔도톡신을 감지하는 데 널리 사용되는 민감하고 정확한 생물학적 검사 방법
19. endotoxin 은 gram-negative bacteria 가 죽거나 용해될 때 발생하는 물질로, 강력한 면역 반응을 유발하며, 고열, 염증, 쇼크, 심한 경우 사망에 이를 수 있음
20. Air sampling (single-stage viable impactor, 400nozzles) 를 통해 airborne bacteria 샘플링을 했다. air flow rate = 28.3L/minute 이고, 3분동안 수집했다. 일정시간 배양 이후, 250 colonies 가 관찰되었다. sampled airvolume 과 bacterial concentration 을 CFU / m3 단위로 구하라. (CFU = colony forming unit)
sampled air volume = flow rate * time = 28.3L/m * 3m = 84.9L
250 colonies 에 대한 positive hole correction = 392CFU
positive hole correction 의 경우, 기기의 종류, 노즐수에 따라 정해진 값이다.250 콜로니가 관찰됐을 때, 실제 콜로니 수에 대한 값을 통계적으로 계산한 값이다.
concentration = corrected CFU / sampled air volume = 392 / 84.9L = 4.617 / L
그런데, 1L = 0.001m3 이다. (1L 는 0.1m * 0.1m * 0.1m 정육면체에 해당하는 부피). 따라서 1000을 곱해주면 4617CFU/m3 이다.
21. 바이러스는 enveloped 와 non-enveloped 로 나눌 수 있다. 외피가 있냐 없냐의 차이로, 바이러스의 특성 (감염 가능성, 환경 변화에 취약한지 등) 에 영향을 미친다. SARS 나 인플루엔자 바이러스는 Enveloped virus 이다.