학습목표¶
- 새로운 내용보다는 기존 내용을 다시 학습하면서 LLM, RAG, Langchain 기초 다지기
In [1]:
'''
LLM : 문자를 이해하고 답변할 수 있는 인공지능모델(알고리즘)
RAG(Retrieval Augmented Genration) : LLM이 대답하기 전에 관련 문서를 찾아서 참고할 수 있도록 도와주는 비서
LangChain : LLM + RAG + AI 연결 조립 키트(LLM, 검색, DB, 체인을 연결해서 자동화 프로그램을 만들 수 있다.)
'''
Out[1]:
'\nLLM : 문자를 이해하고 답변할 수 있는 인공지능모델(알고리즘)\nRAG(Retrieval Augmented Genration) : LLM이 대답하기 전에 관련 문서를 찾아서 참고할 수 있도록 도와주는 비서\nLangChain : LLM + RAG + AI 연결 조립 키트(LLM, 검색, DB, 체인을 연결해서 자동화 프로그램을 만들 수 있다.)\n'
In [67]:
import os
import openai
from openai import OpenAI
from dotenv import load_dotenv
In [68]:
# .env api key load (보안상 안전을 위해서 마스킹)
load_dotenv()
api_key = os.getenv('OPENAI_API_KEY')
def masking(key) :
# 앞 4자리 , 뒤 4자리만 남기고 * 처리
if len(key) <= 8 :
return '*' * len(key)
return key[:4] + '*' * (len(key) - 8) + key[-4:]
masked_api_key = masking(api_key)
# print('masked api key : ', masked_api_key)
In [69]:
print('LLM - ')
client = OpenAI(api_key=api_key)
prompt = input('검색하고자하는 내용을 입력하세요 : ')
print('prompt - ', prompt)
# model : gpt-3.5-turbo - 채팅용 최적화된 가성비 모델
# model : gpt-4o - 텍스트와 이미지/비전 지원을 도와주는 멀티 모델
# model : gpt-4o-mini - 속도/비용 측면에서 유리
system_content='''
당신은 친절한 파이썬 보안 도우미입니다.
사용자의 요청에 대해 항상 보안 모범 사례를 우선으로 설명하고,
민감 정보 노출을 방지하는 방법, 최소 권한 원칙, 패키지/채널 검증, 파일 권한 설정,
취약점 완화 방법을 구체적 명령어와 체크리스트 형태로 제공하십시오.
응답에 실제 비밀번호나 실사용 API 키를 절대 포함하지 마십시오.
'''
user_content=f'''
1) 패키지 설치시 보안 지침
2) 모니터링 권장 설정 방법
3) 민감정보 관리 방법과 예시
4) 가상환경 구축 권장방법 {prompt}'''
response = client.chat.completions.create(
model='gpt-4o-mini',
messages=[
# role : system, user, assistance
# content : content
{'role' : 'system', 'content' : system_content},
{'role' : 'user', 'content' : user_content},
],
# 응답 문장의 길이 제한
max_tokens=512,
# 출력 다양성(무작위성) :보수적, 창의적 : 0~1 낮을수록 보수적
temperature=0.8
)
print('response - ')
print(response)
print()
print('content - ')
print(response.choices[0].message.content)
LLM -
prompt - d
response -
ChatCompletion(id='chatcmpl-Caa1xRttVCp56sLuIWTHObZmFzAgY', choices=[Choice(finish_reason='length', index=0, logprobs=None, message=ChatCompletionMessage(content='보안 모범 사례에 따라 요청하신 내용을 체크리스트 형태로 제공하겠습니다.\n\n### 1) 패키지 설치 시 보안 지침\n- **검증된 소스 사용**:\n - 공식 패키지 인덱스(예: PyPI)에서만 패키지를 설치하세요.\n - `pip install <package>` 명령어 대신, `pip install --no-cache-dir <package>`를 사용하여 캐시를 방지합니다.\n\n- **버전 고정**:\n - 설치 시 특정 버전을 명시하여, 불필요한 보안 문제를 방지합니다.\n ```bash\n pip install <package>==<version>\n ```\n\n- **패키지 서명 확인**:\n - 패키지가 서명되어 있을 경우, 서명을 검증하여 신뢰성을 확인합니다.\n\n### 2) 모니터링 권장 설정 방법\n- **로그 관리**:\n - 로그 작성 시 민감 정보를 포함하지 않도록 주의합니다.\n - 예: `logging` 모듈 사용\n ```python\n import logging\n logging.basicConfig(level=logging.INFO)\n logging.info("Application started")\n ```\n\n- **모니터링 도구 사용**:\n - 중앙 집중식 로깅 시스템(예: ELK Stack, Splunk) 설정을 고려합니다.\n \n- **경고 시스템 설정**:\n - 이상 징후 발생 시 알림을 받을 수 있도록 경고 시스템을 설정합니다.\n - 예: `Prometheus`와 `Grafana`를 통한 모니터링\n\n### 3) 민감정보 관리 방법과 예시\n- **환경 변수 사용**:\n - 애플리케이션 설정에 민감 정보를 직접 포함하지 않고, 환경 변수를 사용합니다.\n ```bash\n export API_KEY="your_api_key_here"\n ```\n\n- **비밀 관리 도구 사용**:\n - `HashiCorp Vault`, `AWS Secrets Manager`와 같은 비밀 관리 도구를 통해 민감 정보를 관리합니다.\n\n- **파일 접근 권한 설정**:\n - 민감 정보가 포함된 파일의 접근 권한을 최소한으로 설정합니다.\n ```bash\n chmod 600 sensitive_file.txt\n ```\n\n### 4) 가상환경 구축 권장 방법\n- **가상환경 생성**:\n - 프로젝트마다 독립적인 가상환경을', refusal=None, role='assistant', audio=None, function_call=None, tool_calls=None, annotations=[]))], created=1762834345, model='gpt-4o-mini-2024-07-18', object='chat.completion', service_tier='default', system_fingerprint='fp_560af6e559', usage=CompletionUsage(completion_tokens=512, prompt_tokens=168, total_tokens=680, completion_tokens_details=CompletionTokensDetails(audio_tokens=0, reasoning_tokens=0, accepted_prediction_tokens=0, rejected_prediction_tokens=0), prompt_tokens_details=PromptTokensDetails(audio_tokens=0, cached_tokens=0)))
content -
보안 모범 사례에 따라 요청하신 내용을 체크리스트 형태로 제공하겠습니다.
### 1) 패키지 설치 시 보안 지침
- **검증된 소스 사용**:
- 공식 패키지 인덱스(예: PyPI)에서만 패키지를 설치하세요.
- `pip install <package>` 명령어 대신, `pip install --no-cache-dir <package>`를 사용하여 캐시를 방지합니다.
- **버전 고정**:
- 설치 시 특정 버전을 명시하여, 불필요한 보안 문제를 방지합니다.
```bash
pip install <package>==<version>
```
- **패키지 서명 확인**:
- 패키지가 서명되어 있을 경우, 서명을 검증하여 신뢰성을 확인합니다.
### 2) 모니터링 권장 설정 방법
- **로그 관리**:
- 로그 작성 시 민감 정보를 포함하지 않도록 주의합니다.
- 예: `logging` 모듈 사용
```python
import logging
logging.basicConfig(level=logging.INFO)
logging.info("Application started")
```
- **모니터링 도구 사용**:
- 중앙 집중식 로깅 시스템(예: ELK Stack, Splunk) 설정을 고려합니다.
- **경고 시스템 설정**:
- 이상 징후 발생 시 알림을 받을 수 있도록 경고 시스템을 설정합니다.
- 예: `Prometheus`와 `Grafana`를 통한 모니터링
### 3) 민감정보 관리 방법과 예시
- **환경 변수 사용**:
- 애플리케이션 설정에 민감 정보를 직접 포함하지 않고, 환경 변수를 사용합니다.
```bash
export API_KEY="your_api_key_here"
```
- **비밀 관리 도구 사용**:
- `HashiCorp Vault`, `AWS Secrets Manager`와 같은 비밀 관리 도구를 통해 민감 정보를 관리합니다.
- **파일 접근 권한 설정**:
- 민감 정보가 포함된 파일의 접근 권한을 최소한으로 설정합니다.
```bash
chmod 600 sensitive_file.txt
```
### 4) 가상환경 구축 권장 방법
- **가상환경 생성**:
- 프로젝트마다 독립적인 가상환경을
In [71]:
'''
도서관 사서 챗봇 시나리오
- 사용자 묻고
- 챗봇(인공지능모델)은 먼저 DB(RAG) 관련 내용을 찾아본 후
- 그 정보를 참고해서 똑똑해진 후
- 사용자에게 응답
'''
from langchain.vectorstores import FAISS
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.text_splitter import CharacterTextSplitter
from langchain.chat_models import ChatOpenAI
from langchain.chains import RetrievalQA
In [77]:
# 외부 DB 개념으로
doc = [
'리스트는 파이썬에서 변경 가능한(mutable) 자료형으로, 요소를 추가하거나 삭제할 수 있습니다.',
'튜플은 변경 불가능한(immutable) 자료형으로, 한 번 생성하면 수정할 수 없습니다.',
'딕셔너리는 키(key)와 값(value)의 쌍으로 데이터를 저장합니다.'
]
In [64]:
# RAG 숫자배열로 변환
text_splitter = CharacterTextSplitter(chunk_size=100, chunk_overlap=50)
texts = text_splitter.create_documents(doc)
print(texts)
[Document(page_content='리스트는 파이썬에서 변경 가능한(mutable) 자료형으로, 요소를 추가하거나 삭제할 수 있습니다.'), Document(page_content='튜플은 변경 불가능한(immutable) 자료형으로, 한 번 생성하면 수정할 수 없습니다.'), Document(page_content='딕셔너리는 키(key)와 값(value)의 쌍으로 데이터를 저장합니다.')]
In [47]:
# embedding
embeddings = OpenAIEmbeddings(model='text-embedding-3-small')
db = FAISS.from_documents(texts, embedding = embeddings)
print(db)
<langchain_community.vectorstores.faiss.FAISS object at 0x00000212DEA8EB90>
In [65]:
# 검색
# as_retriever() : 검색 인터페이스를 이용해서 LLM 연결하는 것
# Retriever 설정
retriever = db.as_retriever(search_kwargs={'k' : 1}) #반환 문서 수:1
print(retriever)
tags=['FAISS', 'OpenAIEmbeddings'] vectorstore=<langchain_community.vectorstores.faiss.FAISS object at 0x00000212DEA8EB90> search_kwargs={'k': 1}
In [72]:
# chain
qa = RetrievalQA.from_chain_type(
llm=ChatOpenAI(model='gpt-4o-mini', temperature=0.9),
# stuff, map_reduce, refune etc....
chain_type='stuff',
retriever = retriever
)
print(qa)
C:\Users\snower\AppData\Local\Temp\ipykernel_9356\2873953294.py:3: LangChainDeprecationWarning: The class `ChatOpenAI` was deprecated in LangChain 0.0.10 and will be removed in 1.0. An updated version of the class exists in the langchain-openai package and should be used instead. To use it run `pip install -U langchain-openai` and import as `from langchain_openai import ChatOpenAI`. llm=ChatOpenAI(model='gpt-4o-mini', temperature=0.9),
combine_documents_chain=StuffDocumentsChain(llm_chain=LLMChain(prompt=ChatPromptTemplate(input_variables=['context', 'question'], messages=[SystemMessagePromptTemplate(prompt=PromptTemplate(input_variables=['context'], template="Use the following pieces of context to answer the user's question. \nIf you don't know the answer, just say that you don't know, don't try to make up an answer.\n----------------\n{context}")), HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['question'], template='{question}'))]), llm=ChatOpenAI(client=<openai.resources.chat.completions.Completions object at 0x00000212DEE76020>, async_client=<openai.resources.chat.completions.AsyncCompletions object at 0x00000212DEF817B0>, model_name='gpt-4o-mini', temperature=0.9, openai_api_key='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', openai_proxy='')), document_variable_name='context') retriever=VectorStoreRetriever(tags=['FAISS', 'OpenAIEmbeddings'], vectorstore=<langchain_community.vectorstores.faiss.FAISS object at 0x00000212DEA8EB90>, search_kwargs={'k': 1})
In [78]:
# 질의 : 문서기반질의(RAG가 강한 부분)
'''
간단한 사실 확인
예제코드 요청
비교-선택 도움
문서기반질의(RAG가 강한 부분)
'''
query = '파이썬 리스트의 튜플의 차이점을 설명해줘'
answer = qa.run(query)
print('Q - ', query)
print('사서가 참고한 내용 - ', retriever.get_relevant_documents(query)[0].page_content)
print('answer - ', answer)
Q - 파이썬 리스트의 튜플의 차이점을 설명해줘 사서가 참고한 내용 - 리스트는 파이썬에서 변경 가능한(mutable) 자료형으로, 요소를 추가하거나 삭제할 수 있습니다. answer - 파이썬 리스트와 튜플의 주요 차이점은 다음과 같습니다. 1. **변경 가능성**: - 리스트(list)는 변경 가능한(mutable) 자료형으로, 요소를 추가하거나 삭제할 수 있습니다. - 튜플(tuple)은 변경 불가능한(immutable) 자료형으로, 생성한 후에는 요소를 변경할 수 없습니다. 2. **구조**: - 리스트는 대괄호([])로 정의되며, 다양한 데이터 타입의 요소를 가질 수 있습니다. - 튜플은 괄호(())로 정의되며, 마찬가지로 다양한 데이터 타입의 요소를 가질 수 있습니다. 3. **성능**: - 튜플은 리스트보다 메모리 사용이 적고, 일부 경우 더 빠르게 동작할 수 있습니다. 이러한 이유로 변경되지 않을 데이터 집합을 저장할 때 튜플을 사용하는 것이 효율적일 수 있습니다. 4. **사용 용도**: - 리스트는 데이터를 수정해야 할 때 주로 사용되며, 튜플은 데이터의 불변성을 보장해야 할 때 사용됩니다. 이러한 차이점들로 인해 상황에 맞게 리스트와 튜플을 선택하여 사용할 수 있습니다.
In [76]:
retriever.get_relevant_documents(query)[0].page_content
C:\Users\snower\AppData\Local\Temp\ipykernel_9356\3521827203.py:1: LangChainDeprecationWarning: The method `BaseRetriever.get_relevant_documents` was deprecated in langchain-core 0.1.46 and will be removed in 1.0. Use invoke instead. retriever.get_relevant_documents(query)
Out[76]:
[Document(page_content='리스트는 파이썬에서 변경 가능한(mutable) 자료형으로, 요소를 추가하거나 삭제할 수 있습니다.')]
In [79]:
retriever.invoke(query)
Out[79]:
[Document(page_content='리스트는 파이썬에서 변경 가능한(mutable) 자료형으로, 요소를 추가하거나 삭제할 수 있습니다.')]
In [ ]: