Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Administrator
geumdo_docs
Commits
932f390a
Commit
932f390a
authored
Jun 18, 2025
by
insun park
Browse files
강의 자료 업데이트 및 용어집 정리
parent
69e437d8
Changes
36
Show whitespace changes
Inline
Side-by-side
ai lecture/source_code/part_6_machine_learning.py
0 → 100644
View file @
932f390a
# Part 6: 머신러닝 기초 실습 (Scikit-learn)
# 이 스크립트를 실행하기 전에 라이브러리를 설치해야 합니다.
# pip install scikit-learn matplotlib
import
numpy
as
np
from
sklearn.model_selection
import
train_test_split
from
sklearn.preprocessing
import
StandardScaler
from
sklearn.linear_model
import
LogisticRegression
from
sklearn.tree
import
DecisionTreeClassifier
from
sklearn.metrics
import
accuracy_score
,
confusion_matrix
,
classification_report
from
sklearn.datasets
import
load_iris
import
matplotlib.pyplot
as
plt
import
seaborn
as
sns
import
os
# --- 데이터 준비 ---
print
(
"--- 1. 데이터 준비 ---"
)
# Scikit-learn에 내장된 붓꽃(Iris) 데이터셋 로드
iris
=
load_iris
()
X
=
iris
.
data
# 특성 (꽃받침 길이/너비, 꽃잎 길이/너비)
y
=
iris
.
target
# 타겟 (품종)
print
(
f
"데이터셋 크기:
{
X
.
shape
}
"
)
print
(
f
"타겟 크기:
{
y
.
shape
}
"
)
print
(
f
"클래스 종류:
{
iris
.
target_names
}
"
)
print
(
"-"
*
30
)
# --- 훈련/테스트 데이터 분리 ---
print
(
"
\n
--- 2. 훈련/테스트 데이터 분리 ---"
)
# 데이터를 훈련용 80%, 테스트용 20%로 분리
# random_state를 고정하여 항상 같은 결과로 분리되도록 함
X_train
,
X_test
,
y_train
,
y_test
=
train_test_split
(
X
,
y
,
test_size
=
0.2
,
random_state
=
42
,
stratify
=
y
)
print
(
f
"훈련 데이터 크기:
{
X_train
.
shape
}
"
)
print
(
f
"테스트 데이터 크기:
{
X_test
.
shape
}
"
)
print
(
"-"
*
30
)
# --- 데이터 스케일링 (특성 표준화) ---
print
(
"
\n
--- 3. 데이터 스케일링 ---"
)
# 특성의 스케일이 다를 경우 모델 성능에 영향을 줄 수 있으므로 표준화 수행
scaler
=
StandardScaler
()
X_train_scaled
=
scaler
.
fit_transform
(
X_train
)
X_test_scaled
=
scaler
.
transform
(
X_test
)
print
(
"데이터 스케일링 완료 (StandardScaler 적용)"
)
print
(
"-"
*
30
)
# --- 모델 훈련 ---
print
(
"
\n
--- 4. 모델 훈련 ---"
)
# 모델 1: 로지스틱 회귀 (Logistic Regression)
log_reg
=
LogisticRegression
(
random_state
=
42
)
log_reg
.
fit
(
X_train_scaled
,
y_train
)
print
(
"로지스틱 회귀 모델 훈련 완료"
)
# 모델 2: 결정 트리 (Decision Tree)
tree_clf
=
DecisionTreeClassifier
(
max_depth
=
3
,
random_state
=
42
)
tree_clf
.
fit
(
X_train_scaled
,
y_train
)
print
(
"결정 트리 모델 훈련 완료"
)
print
(
"-"
*
30
)
# --- 예측 및 평가 ---
print
(
"
\n
--- 5. 예측 및 평가 ---"
)
# 로지스틱 회귀 모델 평가
y_pred_log_reg
=
log_reg
.
predict
(
X_test_scaled
)
accuracy_log_reg
=
accuracy_score
(
y_test
,
y_pred_log_reg
)
print
(
"
\n
--- 로지스틱 회귀 평가 결과 ---"
)
print
(
f
"정확도(Accuracy):
{
accuracy_log_reg
:.
4
f
}
"
)
print
(
"분류 보고서(Classification Report):"
)
print
(
classification_report
(
y_test
,
y_pred_log_reg
,
target_names
=
iris
.
target_names
))
# 결정 트리 모델 평가
y_pred_tree
=
tree_clf
.
predict
(
X_test_scaled
)
accuracy_tree
=
accuracy_score
(
y_test
,
y_pred_tree
)
print
(
"
\n
--- 결정 트리 평가 결과 ---"
)
print
(
f
"정확도(Accuracy):
{
accuracy_tree
:.
4
f
}
"
)
print
(
"분류 보고서(Classification Report):"
)
print
(
classification_report
(
y_test
,
y_pred_tree
,
target_names
=
iris
.
target_names
))
print
(
"-"
*
30
)
# --- 결과 시각화 (혼동 행렬) ---
print
(
"
\n
--- 6. 결과 시각화 ---"
)
# 그래프 저장 디렉터리 확인
output_dir
=
"plot_outputs"
if
not
os
.
path
.
exists
(
output_dir
):
os
.
makedirs
(
output_dir
)
print
(
f
"시각화 결과는 '
{
output_dir
}
' 폴더에 저장됩니다."
)
# 로지스틱 회귀 혼동 행렬
cm_log_reg
=
confusion_matrix
(
y_test
,
y_pred_log_reg
)
plt
.
figure
(
figsize
=
(
8
,
6
))
sns
.
heatmap
(
cm_log_reg
,
annot
=
True
,
fmt
=
'd'
,
cmap
=
'Blues'
,
xticklabels
=
iris
.
target_names
,
yticklabels
=
iris
.
target_names
)
plt
.
title
(
'Logistic Regression - Confusion Matrix'
)
plt
.
xlabel
(
'Predicted Label'
)
plt
.
ylabel
(
'True Label'
)
log_reg_cm_path
=
os
.
path
.
join
(
output_dir
,
"logistic_regression_confusion_matrix.png"
)
plt
.
savefig
(
log_reg_cm_path
)
print
(
f
"로지스틱 회귀 혼동 행렬 저장 완료:
{
log_reg_cm_path
}
"
)
plt
.
close
()
# 결정 트리 혼동 행렬
cm_tree
=
confusion_matrix
(
y_test
,
y_pred_tree
)
plt
.
figure
(
figsize
=
(
8
,
6
))
sns
.
heatmap
(
cm_tree
,
annot
=
True
,
fmt
=
'd'
,
cmap
=
'Greens'
,
xticklabels
=
iris
.
target_names
,
yticklabels
=
iris
.
target_names
)
plt
.
title
(
'Decision Tree - Confusion Matrix'
)
plt
.
xlabel
(
'Predicted Label'
)
plt
.
ylabel
(
'True Label'
)
tree_cm_path
=
os
.
path
.
join
(
output_dir
,
"decision_tree_confusion_matrix.png"
)
plt
.
savefig
(
tree_cm_path
)
print
(
f
"결정 트리 혼동 행렬 저장 완료:
{
tree_cm_path
}
"
)
plt
.
close
()
print
(
"-"
*
30
)
\ No newline at end of file
ai lecture/source_code/part_7_5_llm_application_development.py
0 → 100644
View file @
932f390a
# Part 7.5: LLM 애플리케이션 개발 실습 (LangChain)
# 이 스크립트를 실행하기 전에 라이브러리를 설치해야 합니다.
# pip install langchain langchain_community faiss-cpu sentence-transformers
import
os
from
langchain_community.document_loaders
import
TextLoader
from
langchain.text_splitter
import
CharacterTextSplitter
from
langchain_community.vectorstores
import
FAISS
from
langchain.chains
import
LLMChain
from
langchain_core.prompts
import
PromptTemplate
# --- 모의(Mock) 객체 ---
# 실제 환경에서는 HuggingFaceEmbeddings, ChatOllama 등 실제 모델을 사용해야 합니다.
# 여기서는 API 키나 모델 다운로드 없이 실행 가능하도록 간단한 모의 객체를 사용합니다.
from
langchain.embeddings.base
import
Embeddings
from
langchain.llms.base
import
LLM
from
typing
import
List
,
Any
,
Optional
,
Dict
class
MockEmbeddings
(
Embeddings
):
"""간단한 모의 임베딩 클래스"""
def
embed_documents
(
self
,
texts
:
List
[
str
])
->
List
[
List
[
float
]]:
# 각 텍스트의 길이를 기반으로 간단한 벡터 생성
return
[[
len
(
text
)
/
10
]
for
text
in
texts
]
def
embed_query
(
self
,
text
:
str
)
->
List
[
float
]:
# 쿼리의 길이를 기반으로 간단한 벡터 생성
return
[
len
(
text
)
/
10
]
class
MockLLM
(
LLM
):
"""간단한 모의 LLM 클래스"""
@
property
def
_llm_type
(
self
)
->
str
:
return
"mock"
def
_call
(
self
,
prompt
:
str
,
stop
:
Optional
[
List
[
str
]]
=
None
,
**
kwargs
:
Any
)
->
str
:
return
f
"모의 LLM이 응답합니다: '
{
prompt
}
'라는 질문을 받았습니다."
@
property
def
_identifying_params
(
self
)
->
Dict
[
str
,
Any
]:
return
{
"name"
:
"mock_llm"
}
# --- 1. 문서 준비 및 로드 ---
print
(
"--- 1. 문서 준비 및 로드 ---"
)
# 실습을 위한 간단한 텍스트 파일 생성
doc_content
=
"""
인공지능(AI)은 인간의 학습능력, 추론능력, 지각능력을 인공적으로 구현하려는 컴퓨터 과학의 한 분야입니다.
머신러닝은 AI의 하위 분야로, 기계가 데이터로부터 학습하여 스스로 성능을 향상시키는 기술을 의미합니다.
딥러닝은 머신러닝의 한 종류로, 인공신경망(Artificial Neural Network)을 기반으로 합니다.
최근에는 거대 언어 모델(LLM)이 큰 주목을 받고 있으며, 이는 방대한 텍스트 데이터로 사전 학습된 모델입니다.
RAG(Retrieval-Augmented Generation)는 LLM이 외부 지식 베이스를 참조하여 답변을 생성하는 기술입니다.
"""
doc_path
=
"sample_document.txt"
with
open
(
doc_path
,
"w"
,
encoding
=
"utf-8"
)
as
f
:
f
.
write
(
doc_content
)
# TextLoader로 문서 로드
loader
=
TextLoader
(
doc_path
,
encoding
=
"utf-8"
)
documents
=
loader
.
load
()
print
(
"문서 로드 완료."
)
# print(documents)
print
(
"-"
*
30
)
# --- 2. 문서 분할 (Splitting) ---
print
(
"
\n
--- 2. 문서 분할 ---"
)
text_splitter
=
CharacterTextSplitter
(
chunk_size
=
100
,
chunk_overlap
=
20
)
docs
=
text_splitter
.
split_documents
(
documents
)
print
(
f
"
{
len
(
docs
)
}
개의 조각(chunk)으로 분할되었습니다."
)
# print(docs[0])
print
(
"-"
*
30
)
# --- 3. 임베딩 및 벡터 저장소 생성 (Embedding & Vector Store) ---
print
(
"
\n
--- 3. 임베딩 및 벡터 저장소 생성 ---"
)
# 실제 환경: from langchain_community.embeddings import HuggingFaceEmbeddings
# embeddings = HuggingFaceEmbeddings(model_name="jhgan/ko-sbert-nli")
embeddings
=
MockEmbeddings
()
print
(
f
"사용한 임베딩 모델:
{
type
(
embeddings
).
__name__
}
"
)
# FAISS 벡터 저장소에 문서 임베딩하여 저장
# from_documents: 문서 목록을 받아 임베딩을 수행하고 인덱스를 빌드
vectorstore
=
FAISS
.
from_documents
(
docs
,
embeddings
)
print
(
"FAISS 벡터 저장소 생성 완료."
)
print
(
"-"
*
30
)
# --- 4. 검색 (Retrieval) ---
print
(
"
\n
--- 4. 검색 ---"
)
query
=
"RAG 기술이란 무엇인가요?"
# similarity_search: 쿼리와 가장 유사한 문서를 벡터 공간에서 검색
retrieved_docs
=
vectorstore
.
similarity_search
(
query
,
k
=
1
)
retrieved_text
=
retrieved_docs
[
0
].
page_content
print
(
f
"쿼리: '
{
query
}
'"
)
print
(
f
"검색된 문서: '
{
retrieved_text
}
'"
)
print
(
"-"
*
30
)
# --- 5. 생성 (Generation) - LLM Chain 활용 ---
print
(
"
\n
--- 5. 생성 (RAG) ---"
)
# 실제 환경: from langchain_community.chat_models import ChatOllama
# llm = ChatOllama(model="llama3")
llm
=
MockLLM
()
print
(
f
"사용한 LLM:
{
llm
.
_identifying_params
[
'name'
]
}
"
)
# 프롬프트 템플릿 정의
# 검색된 문서를 'context'로, 사용자의 질문을 'question'으로 받아 프롬프트를 구성
prompt_template
=
"""
주어진 컨텍스트를 바탕으로 질문에 답변해주세요.
컨텍스트: {context}
질문: {question}
답변:
"""
prompt
=
PromptTemplate
.
from_template
(
prompt_template
)
# LLMChain 생성
llm_chain
=
LLMChain
(
llm
=
llm
,
prompt
=
prompt
)
# 검색된 문서와 원본 질문을 이용해 답변 생성
result
=
llm_chain
.
invoke
({
"context"
:
retrieved_text
,
"question"
:
query
})
print
(
"
\n
--- 최종 결과 ---"
)
print
(
f
"질문:
{
result
[
'question'
]
}
"
)
print
(
f
"제공된 컨텍스트:
{
result
[
'context'
]
}
"
)
print
(
f
"생성된 답변:
{
result
[
'text'
]
}
"
)
print
(
"-"
*
30
)
# 임시 파일 삭제
os
.
remove
(
doc_path
)
\ No newline at end of file
ai lecture/source_code/part_7_deep_learning.py
0 → 100644
View file @
932f390a
# Part 7: 딥러닝 기초 실습 (PyTorch)
# 이 스크립트를 실행하기 전에 라이브러리를 설치해야 합니다.
# pip install torch torchvision scikit-learn
import
torch
import
torch.nn
as
nn
import
torch.optim
as
optim
from
torch.utils.data
import
DataLoader
,
TensorDataset
from
sklearn.model_selection
import
train_test_split
from
sklearn.preprocessing
import
StandardScaler
from
sklearn.datasets
import
load_iris
from
sklearn.metrics
import
accuracy_score
import
numpy
as
np
# --- 1. 데이터 준비 및 전처리 ---
print
(
"--- 1. 데이터 준비 및 전처리 ---"
)
# Scikit-learn에 내장된 붓꽃(Iris) 데이터셋 로드
iris
=
load_iris
()
X
=
iris
.
data
y
=
iris
.
target
# 훈련/테스트 데이터 분리
X_train
,
X_test
,
y_train
,
y_test
=
train_test_split
(
X
,
y
,
test_size
=
0.2
,
random_state
=
42
,
stratify
=
y
)
# 데이터 스케일링
scaler
=
StandardScaler
()
X_train_scaled
=
scaler
.
fit_transform
(
X_train
)
X_test_scaled
=
scaler
.
transform
(
X_test
)
# PyTorch 텐서로 변환
X_train_tensor
=
torch
.
FloatTensor
(
X_train_scaled
)
y_train_tensor
=
torch
.
LongTensor
(
y_train
)
X_test_tensor
=
torch
.
FloatTensor
(
X_test_scaled
)
y_test_tensor
=
torch
.
LongTensor
(
y_test
)
# DataLoader 생성
# 딥러닝 모델은 보통 미니배치 단위로 학습하므로 DataLoader를 사용
train_dataset
=
TensorDataset
(
X_train_tensor
,
y_train_tensor
)
train_loader
=
DataLoader
(
dataset
=
train_dataset
,
batch_size
=
16
,
shuffle
=
True
)
print
(
"PyTorch 텐서 및 DataLoader 준비 완료"
)
print
(
f
"훈련 데이터 크기:
{
X_train_tensor
.
shape
}
"
)
print
(
f
"훈련 타겟 크기:
{
y_train_tensor
.
shape
}
"
)
print
(
"-"
*
30
)
# --- 2. 딥러NING 모델 정의 ---
print
(
"
\n
--- 2. 딥러닝 모델 정의 ---"
)
class
SimpleNN
(
nn
.
Module
):
def
__init__
(
self
,
input_size
,
hidden_size
,
num_classes
):
super
(
SimpleNN
,
self
).
__init__
()
self
.
fc1
=
nn
.
Linear
(
input_size
,
hidden_size
)
self
.
relu
=
nn
.
ReLU
()
self
.
fc2
=
nn
.
Linear
(
hidden_size
,
num_classes
)
def
forward
(
self
,
x
):
out
=
self
.
fc1
(
x
)
out
=
self
.
relu
(
out
)
out
=
self
.
fc2
(
out
)
return
out
# 모델 파라미터 설정
input_size
=
X_train
.
shape
[
1
]
# 특성의 수: 4
hidden_size
=
32
num_classes
=
len
(
np
.
unique
(
y_train
))
# 클래스의 수: 3
learning_rate
=
0.01
num_epochs
=
50
model
=
SimpleNN
(
input_size
,
hidden_size
,
num_classes
)
print
(
"모델 구조:"
)
print
(
model
)
print
(
"-"
*
30
)
# --- 3. 손실 함수 및 옵티마이저 정의 ---
print
(
"
\n
--- 3. 손실 함수 및 옵티마이저 정의 ---"
)
# 다중 분류 문제이므로 CrossEntropyLoss 사용
criterion
=
nn
.
CrossEntropyLoss
()
# Adam 옵티마이저 사용
optimizer
=
optim
.
Adam
(
model
.
parameters
(),
lr
=
learning_rate
)
print
(
f
"손실 함수:
{
criterion
}
"
)
print
(
f
"옵티마이저:
{
optimizer
}
"
)
print
(
"-"
*
30
)
# --- 4. 모델 훈련 ---
print
(
"
\n
--- 4. 모델 훈련 ---"
)
for
epoch
in
range
(
num_epochs
):
for
i
,
(
features
,
labels
)
in
enumerate
(
train_loader
):
# 순전파 (Forward pass)
outputs
=
model
(
features
)
loss
=
criterion
(
outputs
,
labels
)
# 역전파 및 최적화 (Backward and optimize)
optimizer
.
zero_grad
()
# 이전 그래디언트 초기화
loss
.
backward
()
# 그래디언트 계산
optimizer
.
step
()
# 가중치 업데이트
if
(
epoch
+
1
)
%
10
==
0
:
print
(
f
'Epoch [
{
epoch
+
1
}
/
{
num_epochs
}
], Loss:
{
loss
.
item
():.
4
f
}
'
)
print
(
"모델 훈련 완료"
)
print
(
"-"
*
30
)
# --- 5. 모델 평가 ---
print
(
"
\n
--- 5. 모델 평가 ---"
)
# 모델을 평가 모드로 설정 (dropout, batchnorm 등 비활성화)
model
.
eval
()
# 테스트 데이터로 예측
with
torch
.
no_grad
():
# 그래디언트 계산 비활성화
outputs
=
model
(
X_test_tensor
)
# 가장 높은 확률을 가진 클래스를 예측값으로 선택
_
,
predicted
=
torch
.
max
(
outputs
.
data
,
1
)
accuracy
=
accuracy_score
(
y_test_tensor
.
numpy
(),
predicted
.
numpy
())
print
(
f
'테스트 데이터 정확도:
{
100
*
accuracy
:.
2
f
}
%'
)
# 일부 예측 결과 확인
print
(
"
\n
일부 샘플 예측 결과:"
)
print
(
f
"실제 값:
{
y_test_tensor
[:
10
].
numpy
()
}
"
)
print
(
f
"예측 값:
{
predicted
[:
10
].
numpy
()
}
"
)
print
(
"-"
*
30
)
\ No newline at end of file
ai lecture/source_code/part_8_fastapi_project/api.py
0 → 100644
View file @
932f390a
# api.py
# API 엔드포인트의 실제 로직을 정의합니다.
from
fastapi
import
APIRouter
,
HTTPException
from
sklearn.datasets
import
load_iris
from
sklearn.tree
import
DecisionTreeClassifier
import
numpy
as
np
from
.
import
schemas
# 현재 패키지(디렉터리)의 schemas 모듈을 임포트
# --- 모델 준비 ---
# 실제 프로덕션 환경에서는 미리 학습되고 저장된 모델 파일(e.g., .joblib, .pkl)을 로드해야 합니다.
# 여기서는 실습 편의를 위해 서버 시작 시 간단한 모델을 학습시켜 메모리에 올립니다.
iris
=
load_iris
()
X
=
iris
.
data
y
=
iris
.
target
# 간단한 결정 트리 모델 훈련
model
=
DecisionTreeClassifier
(
max_depth
=
3
,
random_state
=
42
)
model
.
fit
(
X
,
y
)
model_info
=
{
"name"
:
"Iris Species Predictor"
,
"version"
:
"1.0"
,
"description"
:
"A simple Decision Tree classifier for Iris species."
}
print
(
f
"'
{
model_info
[
'name'
]
}
' 모델이 준비되었습니다."
)
# --- API 라우터 설정 ---
# APIRouter를 사용하면 엔드포인트를 모듈화하여 관리할 수 있습니다.
router
=
APIRouter
()
@
router
.
get
(
"/model"
,
response_model
=
schemas
.
ModelInfo
)
async
def
get_model_info
():
"""로드된 머신러닝 모델의 정보를 반환합니다."""
return
model_info
@
router
.
post
(
"/predict"
,
response_model
=
schemas
.
IrisPrediction
)
async
def
predict_species
(
iris_input
:
schemas
.
IrisInput
):
"""
붓꽃의 특성(sepal/petal length/width)을 입력받아 품종을 예측합니다.
- **입력**: 붓꽃의 4가지 특성 (JSON)
- **출력**: 예측된 품종 이름과 클래스 번호 (JSON)
"""
try
:
# Pydantic 모델에서 받은 입력을 numpy 배열로 변환
input_data
=
np
.
array
([[
iris_input
.
sepal_length
,
iris_input
.
sepal_width
,
iris_input
.
petal_length
,
iris_input
.
petal_width
]])
# 모델 예측
prediction_value
=
model
.
predict
(
input_data
)
predicted_class_index
=
int
(
prediction_value
[
0
])
# 예측된 클래스 인덱스에 해당하는 품종 이름 찾기
predicted_species_name
=
iris
.
target_names
[
predicted_class_index
]
return
schemas
.
IrisPrediction
(
species_name
=
predicted_species_name
,
prediction
=
predicted_class_index
)
except
Exception
as
e
:
# 예외 발생 시, 서버 에러(500)와 함께 상세 내용을 반환
raise
HTTPException
(
status_code
=
500
,
detail
=
str
(
e
))
\ No newline at end of file
ai lecture/source_code/part_8_fastapi_project/main.py
0 → 100644
View file @
932f390a
# main.py
# FastAPI 애플리케이션을 생성하고, 라우터를 포함시켜 서버를 실행하는 진입점입니다.
import
uvicorn
from
fastapi
import
FastAPI
from
.
import
api
# api.py에서 정의한 라우터를 임포트
# FastAPI 앱 인스턴스 생성
app
=
FastAPI
(
title
=
"AI 모델 서빙 API"
,
description
=
"머신러닝 모델을 서빙하기 위한 FastAPI 기반 API입니다."
,
version
=
"1.0.0"
)
# 루트 경로
@
app
.
get
(
"/"
)
async
def
root
():
return
{
"message"
:
"AI 모델 서빙 API에 오신 것을 환영합니다. /docs 로 이동하여 API 문서를 확인하세요."
}
# api.py에서 정의한 라우터를 앱에 포함
# prefix="/api/v1"을 설정하여 모든 관련 엔드포인트가 이 경로 하위에 위치하도록 함
app
.
include_router
(
api
.
router
,
prefix
=
"/api/v1"
,
tags
=
[
"Iris Prediction"
])
# 이 파일이 직접 실행될 때 uvicorn 서버를 시작합니다.
# 터미널에서 `python main.py`를 실행하거나,
# `uvicorn part_8_fastapi_project.main:app --reload` 명령어로 실행할 수 있습니다.
if
__name__
==
"__main__"
:
uvicorn
.
run
(
"part_8_fastapi_project.main:app"
,
host
=
"0.0.0.0"
,
port
=
8000
,
reload
=
True
)
\ No newline at end of file
ai lecture/source_code/part_8_fastapi_project/requirements.txt
0 → 100644
View file @
932f390a
fastapi
uvicorn
pydantic
scikit-learn
numpy
\ No newline at end of file
ai lecture/source_code/part_8_fastapi_project/schemas.py
0 → 100644
View file @
932f390a
# schemas.py
# API의 요청(Request) 및 응답(Response) 데이터 형식을 정의합니다.
from
pydantic
import
BaseModel
from
typing
import
List
,
Optional
class
IrisInput
(
BaseModel
):
"""붓꽃 예측을 위한 입력 데이터 형식"""
sepal_length
:
float
sepal_width
:
float
petal_length
:
float
petal_width
:
float
class
Config
:
# Pydantic 모델이 API 문서에 예시로 보일 때 사용될 값
json_schema_extra
=
{
"example"
:
{
"sepal_length"
:
5.1
,
"sepal_width"
:
3.5
,
"petal_length"
:
1.4
,
"petal_width"
:
0.2
}
}
class
IrisPrediction
(
BaseModel
):
"""붓꽃 예측 결과 형식"""
species_name
:
str
prediction
:
int
class
ModelInfo
(
BaseModel
):
"""현재 로드된 모델의 정보를 담는 형식"""
name
:
str
version
:
str
description
:
str
\ No newline at end of file
ai lecture/source_code/part_9_fastapi_production/Dockerfile
0 → 100644
View file @
932f390a
# Dockerfile
# 1. 베이스 이미지 설정
# 공식 Python 3.9 슬림 버전을 사용하여 이미지 크기를 최적화합니다.
FROM
python:3.9-slim
# 2. 작업 디렉터리 설정
# 컨테이너 내에서 작업이 수행될 기본 경로를 설정합니다.
WORKDIR
/app
# 3. 환경 변수 설정
# 파이썬이 .pyc 파일을 생성하지 않도록 하고, 버퍼링을 비활성화하여 로그가 즉시 출력되도록 합니다.
ENV
PYTHONDONTWRITEBYTECODE 1
ENV
PYTHONUNBUFFERED 1
# 4. 의존성 설치
# 먼저 의존성 정의 파일만 복사하여 설치합니다.
# 이렇게 하면 소스 코드가 변경되어도 의존성이 동일한 경우 Docker 캐시를 활용하여 빌드 속도를 높일 수 있습니다.
COPY
requirements.txt .
RUN
pip
install
--no-cache-dir
--upgrade
pip
&&
\
pip
install
--no-cache-dir
-r
requirements.txt
# 5. 애플리케이션 코드 복사
# 로컬의 app 디렉터리에 있는 모든 소스 코드를 컨테이너의 /app/app 디렉터리로 복사합니다.
COPY
./app /app/app
# 6. 포트 노출
# 애플리케이션이 컨테이너의 8000번 포트에서 실행될 것임을 명시합니다.
EXPOSE
8000
# 7. 서버 실행 명령어
# Gunicorn을 사용하여 FastAPI 애플리케이션을 실행합니다.
# -w 4: 4개의 워커 프로세스를 사용합니다. (CPU 코어 수에 따라 조절)
# -k uvicorn.workers.UvicornWorker: Uvicorn 호환 워커 클래스를 사용합니다.
# app.main:app: app/main.py 파일의 app 인스턴스를 의미합니다.
# -b 0.0.0.0:8000: 모든 네트워크 인터페이스의 8000번 포트에 바인딩합니다.
CMD
["gunicorn", "-w", "4", "-k", "uvicorn.workers.UvicornWorker", "app.main:app", "-b", "0.0.0.0:8000"]
\ No newline at end of file
ai lecture/source_code/part_9_fastapi_production/app/__init__.py
0 → 100644
View file @
932f390a
# This file makes the 'app' directory a Python package.
\ No newline at end of file
ai lecture/source_code/part_9_fastapi_production/app/api.py
0 → 100644
View file @
932f390a
# app/api.py
from
fastapi
import
APIRouter
,
HTTPException
from
sklearn.datasets
import
load_iris
from
sklearn.tree
import
DecisionTreeClassifier
import
numpy
as
np
from
.
import
schemas
# Model Preparation
iris
=
load_iris
()
X
=
iris
.
data
y
=
iris
.
target
model
=
DecisionTreeClassifier
(
max_depth
=
3
,
random_state
=
42
)
model
.
fit
(
X
,
y
)
model_info
=
{
"name"
:
"Iris Species Predictor"
,
"version"
:
"1.0"
,
"description"
:
"A simple Decision Tree classifier for Iris species."
}
print
(
f
"'
{
model_info
[
'name'
]
}
' model is ready."
)
# API Router
router
=
APIRouter
()
@
router
.
get
(
"/model"
,
response_model
=
schemas
.
ModelInfo
)
async
def
get_model_info
():
"""Returns information about the loaded machine learning model."""
return
model_info
@
router
.
post
(
"/predict"
,
response_model
=
schemas
.
IrisPrediction
)
async
def
predict_species
(
iris_input
:
schemas
.
IrisInput
):
"""
Predicts the species of an Iris flower based on its features.
- **Input**: Four features of the Iris flower (JSON).
- **Output**: Predicted species name and class index (JSON).
"""
try
:
input_data
=
np
.
array
([[
iris_input
.
sepal_length
,
iris_input
.
sepal_width
,
iris_input
.
petal_length
,
iris_input
.
petal_width
]])
prediction_value
=
model
.
predict
(
input_data
)
predicted_class_index
=
int
(
prediction_value
[
0
])
predicted_species_name
=
iris
.
target_names
[
predicted_class_index
]
return
schemas
.
IrisPrediction
(
species_name
=
predicted_species_name
,
prediction
=
predicted_class_index
)
except
Exception
as
e
:
raise
HTTPException
(
status_code
=
500
,
detail
=
str
(
e
))
\ No newline at end of file
ai lecture/source_code/part_9_fastapi_production/app/main.py
0 → 100644
View file @
932f390a
# app/main.py
import
uvicorn
from
fastapi
import
FastAPI
from
.
import
api
app
=
FastAPI
(
title
=
"Production-Ready AI Model API"
,
description
=
"A production-ready API for serving ML models using FastAPI and Docker."
,
version
=
"2.0.0"
)
@
app
.
get
(
"/"
)
async
def
root
():
return
{
"message"
:
"Welcome to the Production-Ready AI API. See /docs for documentation."
}
app
.
include_router
(
api
.
router
,
prefix
=
"/api/v1"
,
tags
=
[
"Iris Prediction"
])
# Note: The uvicorn.run() part is typically removed for production,
# as the server will be started by a process manager like Gunicorn or Uvicorn directly
# from the command line, as defined in the Dockerfile.
# We keep it here for consistency in the course material.
if
__name__
==
"__main__"
:
uvicorn
.
run
(
"main:app"
,
host
=
"0.0.0.0"
,
port
=
8000
,
reload
=
True
,
app_dir
=
"/app"
)
\ No newline at end of file
ai lecture/source_code/part_9_fastapi_production/app/schemas.py
0 → 100644
View file @
932f390a
# app/schemas.py
from
pydantic
import
BaseModel
from
typing
import
List
,
Optional
class
IrisInput
(
BaseModel
):
sepal_length
:
float
sepal_width
:
float
petal_length
:
float
petal_width
:
float
class
Config
:
json_schema_extra
=
{
"example"
:
{
"sepal_length"
:
5.1
,
"sepal_width"
:
3.5
,
"petal_length"
:
1.4
,
"petal_width"
:
0.2
}
}
class
IrisPrediction
(
BaseModel
):
species_name
:
str
prediction
:
int
class
ModelInfo
(
BaseModel
):
name
:
str
version
:
str
description
:
str
\ No newline at end of file
ai lecture/source_code/part_9_fastapi_production/docker-compose.yml
0 → 100644
View file @
932f390a
# docker-compose.yml
version
:
'
3.8'
services
:
# 서비스 이름 (임의로 지정 가능)
fastapi-service
:
# 빌드 컨텍스트: 현재 디렉터리(.)의 Dockerfile을 사용하여 이미지를 빌드
build
:
.
# 컨테이너 이름
container_name
:
production_api_server
# 포트 매핑: 호스트의 8000번 포트를 컨테이너의 8000번 포트와 연결
ports
:
-
"
8000:8000"
# 재시작 정책: 컨테이너가 예기치 않게 종료될 경우 항상 다시 시작
restart
:
always
# 환경 설정 (필요시 추가)
# environment:
# - KEY=VALUE
\ No newline at end of file
ai lecture/source_code/part_9_fastapi_production/requirements.txt
0 → 100644
View file @
932f390a
# requirements.txt
fastapi
uvicorn
# Gunicorn is a popular choice for running python web applications in production
gunicorn
scikit-learn
numpy
\ No newline at end of file
ai_lecture_starter_kit/Dockerfile
deleted
100644 → 0
View file @
69e437d8
# 1. 베이스 이미지 설정
# 공식 Python 3.9 이미지를 기반으로 합니다.
FROM
python:3.9-slim
# 2. 작업 디렉토리 설정
# 컨테이너 내에서 명령이 실행될 기본 경로입니다.
WORKDIR
/app
# 3. 의존성 설치
# 먼저 requirements.txt 파일만 복사하여 캐시를 활용합니다.
# 이렇게 하면 소스 코드가 변경되어도 매번 의존성을 새로 설치하지 않습니다.
COPY
requirements.txt .
RUN
pip
install
--no-cache-dir
-r
requirements.txt
# 4. 소스 코드 복사
# 현재 디렉토리의 모든 파일을 컨테이너의 /app 디렉토리로 복사합니다.
COPY
. .
# 5. 포트 노출
# FastAPI 기본 포트인 8000번을 외부에 노출합니다.
EXPOSE
8000
# 6. 애플리케이션 실행
# 컨테이너가 시작될 때 실행할 명령입니다.
# Uvicorn을 사용하여 main.py 파일의 app 객체를 실행합니다.
CMD
["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
\ No newline at end of file
ai_lecture_starter_kit/docker-compose.yml
deleted
100644 → 0
View file @
69e437d8
version
:
'
3.8'
services
:
ai-lecture-service
:
# 빌드에 사용할 Dockerfile의 경로를 지정합니다.
# '.'는 현재 디렉토리를 의미합니다.
build
:
.
# 컨테이너의 이름을 지정합니다.
container_name
:
ai_lecture_container
# 포트 매핑을 설정합니다.
# "호스트 포트:컨테이너 포트" 형식입니다.
ports
:
-
"
8000:8000"
# 볼륨 매핑을 설정합니다.
# 현재 디렉토리(.)의 모든 파일을 컨테이너의 /app 디렉토리와 동기화합니다.
# 이를 통해 호스트에서 코드를 수정하면 즉시 컨테이너에 반영됩니다.
volumes
:
-
.:/app
# 컨테이너가 항상 재시작되도록 설정합니다.
restart
:
always
\ No newline at end of file
Prev
1
2
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment