[인공지능사관학교: 자연어분석A반] Node.js / LangChain (4)

Suhyeon Lee·2025년 8월 29일

목차

Ⅰ. 오전 수업
	A. 1교시: Node.js 개념 익히기
		1. 웹이란 무엇인가
		2. Node.js
		3. 노드의 특성
        4. Node.js 설치
	B. 2교시: 노드 기초 실습
		1. 모듈
		2. http 모듈
	C. 3교시: Node.js
		1. http 모듈 (cont.)
		2. req

Ⅱ. 오후 수업
	A. 4교시: LangChain
		1. 지난 시간 복습
		2. Zero-Shot Prompting 정리
		3. 퓨샷 프롬프팅
	B. 5교시: LangChain
		1. 퓨샷 프롬프팅 (cont.)
		2. ExampleSelector
	C. 6교시: LangChain
		1. Callbacks: 스트리밍

Ⅲ. CAREER UP
	미니 프로젝트 전체 발표

Ⅳ. 하루 돌아보기




Ⅰ. 오전 수업

A. 1교시: Node.js 개념 익히기

내 손 안의 Web Application을 만들어보자!

  • 우리가 만든 HTML, CSS, JS 화면 → 실제 '서버'에 넣어 동작을 해야 브라우저에 가서 볼 수 있음
    • HTML, CSS, JS 언어를 활용할 수 있는 기술이 필요
    • 이제까지 화면을 본 건 vscode live server 덕분
      • 로컬 환경에서 서버 세팅 없이 내가 작성한 코드를 실제 브라우저에서 동작할 수 있게 실행할 수 있는 환경을 제공하는 모듈 (포트 번호 5500)
      • 보여주는 용도만 가능 (데이터를 연결한다던지 전송한다던지 하는 작업은 불가능)
  • 따라서 우리는 오늘부터 '서버'를 만들 것
    • 하나의 컴퓨터에서 가상 공간을 쪼개 쓰는 개념: 웹용 노드, React, …

1. 웹이란 무엇인가

  • WEB의 등장(1990)
    • 정보를 웹 페이지에 표현하고 인터넷을 통해 전송이 가능
    • 웹 등장 전: 종이 서류로 문서화 → 웹: HTML 문서
  • 웹의 기본 구조 (통신)
    • 과거의 웹 사이트: 단순 정보 제공 목적. 사용자가 할 수 있는 게 별로 없었음(글만 보고 나가는 일방적 소통)
    • 과거 서버 구조 → 단순히 HTML을 저장하고 응답해주는 컴퓨터
      • 메인 페이지
      • 로그인 페이지
  • request와 response
    • request: Client가 Server에게 보내는 데이터가 담겨 있는 공간
    • response: Server가 Client에게 보내는 데이터가 담겨 있는 공간
  • 서버(Server)?
    • 초기: 단순히 HTML을 저장하고 응답해주는 컴퓨터
      • 애초에 사용자도 적고 개발자가 만든 페이지의 수도 적었기 때문
    • 점점 사용자가 많아지고 사이트 규모가 커지면서 사람이 직접 HTML을 코딩해서 만드는 구조에 지침 → 그렇다면 기계에게 HTML 작성을 시켜보면 어떨까?: 개발자는 하나의 껍데기만 만들고 그 안에 있는 값들은 컴퓨터가 채우도록 (== 페이지 생산을 컴퓨터가 하도록) → 서버 프로그램 등장

네이버 로그인 후 화면 예시로 들어주신 거 기억하기: 과거에는 개발자가 모든 페이지를 하나하나 다 만들어야 했다면, 현재는 개발자가 껍데기만 만들고 실제 안의 값을 갈아끼우는 건 컴퓨터가 알아서 자동으로 함 (HTML 파일 하나를 가지고 컴퓨터가 값을 끼워 넣어서 그 데이터를 수많은 유저에게 전송)

  • 정적 페이지(Static Web)
    • 내용이 멈춰 있는 페이지
    • 어떤 사용자가 들어와도 똑같은 화면을 볼 수 있는 환경
      • 우리가 이제까지 실습한 모든 페이지는 정적 페이지임
  • 동적 페이지(Dynamic Web)
  • 페이지에 변화가 많은 페이지
  • 사용자마다 보이는 화면이 다름 ← 컴퓨터가 생성을 하는 동적 페이지

  • 서버 프로그램
    • "HTML 껍데기 하나만 만들어 놓고 실질적으로 페이지 만드는 건 서버가 만들자!" → 어떤 언어로? → "기존 언어를 활용해 서버 프로그램을 만들어보자!" → JAVA / JS / Python

2. Node.js

  • 웹 등장 → 기계에게 HTML 작성을 시켜보자 → 기존 언어를 활용해 서버프로그램을 만들자
  • 2008년 크롬 웹 브라우저에서 동작하는 V8엔진 개발 → 자바스크립트의 성능 개선 → Ryan Dahl: 자바스크립트 너무 좋다… 브라우저 말고 다른 곳에서도 쓰고 싶어! → Node.js 개발: V8 엔진을 떼 와 JS가 동작하는 환경을 가상으로 만들어(런타임 환경) 어디서든 동작하도록 만듦
    • V8엔진에거 가장 동작을 잘 하고 지향하는 방향성임
    • 자바스크립트의 특징 → 확장성 문제: 웹 브라우저에서만 쓸 수 있음 == 동작하는 환경 자체가 웹 브라우저 (cf. JAVA는 태생부터 가전제품, IoT 등 확장성이 뛰어남)

web browser 제어 → Computer 제어
JavaScript       Node.js

  • 메인 서버를 node.js로 쓰는 회사들
    • NASA, Google, amazon, Netflix, …
  • Node.js
    • Chrome V8 자바스크립트 엔진으로 빌드된 자바스크립트 런타임
      • 런타임: 특정 언어로 만든 프로그램들을 실행할 수 있는 환경
      • 주의: Node.js 자체가 서버인 게 아님! Node.js 환경 위에 서버를 만드는 것
    • 자바스크립트를 구동할 수 있는 브라우저 밖에 환경을 제공하는 것
  • Node.js 중요 개념들
    1. Event - driven
    2. Non-blocking I/O
    3. Single Thread ★★★
    4. NPM

3. 노드의 특성

  1. 이벤트 기반(Event-Driven) 기술
    • 이벤트가 발생할 때 미리 지정해둔 작업을 수행하는 방식
      • 예: 클릭했을 때 경고창이 뜬다, 네트워크 요청이 들어왔을 때 페이지를 띄워준다.
    • 이벤트에만 작동하기 때문에 자원을 최소화할 수 있다
      • 예: 채팅창 → 서버가 24시간 돌아가는 게 아니라 메시지를 보낼 때만 열림
    • 단점: 대규모 서비스에는 적합하지 않음

서비스의 특징에 맞는 개발이 필요! → 24시간 돌아가는 서버가 필요하면 Node.js는 X

  1. Non-Blocking I/O
    • 이전 작업이 완료될 때까지 멈추지 않고 다음 작업을 진행하는 방식
    • Node.js는 기준 자체가 비동기! → 동기 형태가 필요하면 따로 코드 짜야 함

동기와 비동기 특징

  • 동기 통신:
    • 많은 양의 데이터를 처리
      • 단순 업무 처리에는 부족한 부분이 있음
    • 앞쪽부터 순차적으로 처리해 뒤쪽은 기다리게 만들 수 있음 → 티켓팅 서비스
  • 비동기 통신:
    • 업무를 한 번에 받아서 처리 & 빨리 끝나는 것부터 처리 → 짧은 업무에 효율적
      • 짧은 업무에는 효율적이지만 많은 업무를 처리할 때는 불편 (코드 순서 짜는 게 어려움)
      • '빨리 끝나는 것'은 컴퓨터가 스스로 판단 → 연관성이 있는 코드라면(앞선 결과를 뒤에서 쓰는 경우) 비동기로 작업 시 오류 → 이럴 때는 동기로 따로 지정
Blocking(동기)Non-Blocking(비동기)
설계가 매우 간단하고 직관적결과가 주어지는데 시간이 걸리더라도 그 시간 동안 다른 작업 가능
결과가 주어질 때까지 대기
→ 시간 효율이 좋지 못함
동기보다 코드 짜기 복잡
  1. Single Thread ★
    • 한 번에 하나의 일만 처리할 수 있는 방식
    • 싱글 스레드와 멀티 스레드
      • Single Thread & Blocking 방식 일처리 → 매우 비효율적
      • Single Thread & Non-Blocking 방식 일처리
      • Multi-Thread 방식 일처리 → 용량과 메모리를 훨씬 많이 차지
    • 자바는 멀티 스레드를 지향 → 대규모 서비스는 자바
    • 단방향 빠른 통신 → 싱글 스레드: 채팅 서비스
    • 사용자가 동시에 엄청 많을 때 → 멀티 스레드: 스트리밍 서비스
  1. NPM(Node Package Manager; 노드 패키지 관리자)
    • Node.js에서 만들어 사용하는 모듈들을 패키지로 만들어 통합 관리 및 배포
  • 정리
    1. 자바스트립트를 사용해 서버단 로직 처리
    2. 이벤트 기반 비동기 방식이라 서버 무리 적음
    3. NPM을 이용한 다양한 모듈 제공
    4. 구글이 만드는 JavaScript V8 엔진

4. Node.js 설치

Node.js is a cross-platform, open-source JavaScript runtime environment that can run on Windows, Linux, Unix, macOS, and more. Node.js runs on the V8 JavaScript engine, and executes JavaScript code outside a web browser. Node.js lets developers use JavaScript to write command line tools and server-side scripting.

  • Node.js® 다운로드
    • 브라우저가 아닌 내 컴퓨터에서 쓰기 위함
    • 자바스크립트는 왜 설치를 안 했을까? 웹 브라우저가 설지되어 있으면 바로 쓸 수 있음! (JS는 브라우저에서만 쓰던 언어였으니까)
  • window+R → cmd → node -v 실행 시 아래와 같이 나오면 OK

B. 2교시: 노드 기초 실습

1. 모듈

  • 모듈(module)
    • 필요한 기능별로 모아 둔 퍼즐/부품 → 라이브러리
    • 필요할 때마다 가져와 붙여 쓴다
  • 모듈 3가지
    1. 내장 모듈 → 기본으로 설치가 되어 있는 모듈 (많이 사용하는 모듈들)
    2. 자체 제작 모듈 → 내가 직접 제작하는 모듈
    3. 외장 모듈 → 다른 사람들이 만들어 놓은 모듈 → 반드시 설치가 필요하다.
    • 공통점: 반드시 처음에 import를 진행한다. → ★ require

a. 더하기 모듈 만들기

let num1 = 10;
let num2 = 20;
let result = num1 + num2;

module.exports = {result};
  • 핵심: 내가 직접 모듈을 만들 때는 반드시 마지막 줄에 수출 진행
    • 리턴문 생각하면 됨
    • module.exports = {result};

b. 완성된 더하기 모듈을 불러와서 콘솔창에 출력

  • 모듈을 저장할 때는 'const'! (함수, 모듈, 키 값 → const)
const {result} = require("./0_add_module");
// './'는 내 위치라는 뜻. 값을 가져올 때는 중괄호로 받는다.
// 모델을 불러올 때 모델명 뒤 확장자(.js)는 생략 가능

console.log(result)
  • 터미널 창 열기(ctrl + `)
    • 터미널은 서버 개발자가 주로 사용하는 환경
    • 자주 쓸 터미널 명령어
      1) 파일 조회: ls
      2) 경로 변경: cd
      3) js 파일 실행: node "실행할 파일명"
  • 노드에서는 경로 파악이 가장 중요
    • 터미널에서 명령어 ls (list의 단축어) → 현재 내가 와 있는 폴더에서 내부 파일을 조회하는 명령어
  • 터미널에서 첫 번째 글자 적고 tab 누르면 자동완성됨
    • 위에 있는 명령어 지울 때는 clear
    • console.log() 값이 잘 출력됨을 확인
  • 포인트
    1. 폴더 위치 잘 확인하기
    2. 실행 명령어: node "실행할 파일명"

설치 반영이 안 된 경우 아래와 같이 오류가 뜰 수 있음 (vscode 다 껐다가 다시 켜보기

2. http 모듈

  • http 모듈은 가장 오래되고 가장 대중화된 모듈
    • 하지만 요즘은 시대가 바뀌어 거의 사용하지 않음
      • 현재는 Express로 서버를 제작한다
    • 서버를 만드는 모듈: 종류가 엄청 다양함
  • 로컬로 간단한 서버를 제작할 때 활용한다
  • 내장 모듈
  • 내 컴퓨터에 나만의 서버를 제작 → 로컬 서버
  • 옛날 모듈이라 많은 일을 한번에 할 수 없음
const http = require("http");

http.createServer((req,res)=>{
    console.log("누군가 접속했어요!!");
}).listen(3000);
  • const http = require("http");
    • python alias랑 비슷한 개념이라고 생각하면 됨
    • 보통 모듈 이름과 동일하게 적음

C. 3교시

1. http 모듈 (cont.)

  • 포트 번호
    • 창구 번호라고 생각하면 편함
    • 같은 컴퓨터 내에서는 절대 중복되면 안 됨! → 충돌 발생
      • 같은 집에 같은 방 번호 X
      • 컴퓨터가 다르면 상관없음
    • 보통 자바 계열은 8000번대, react나 node는 3000번대, vscode live server는 5500
  • 작성한 코드 실행
    • TERMINAL에서 node .\1_http모듈.js
      • 아래와 같은 창이 뜨면 확인 누르기
      • 터미널 창에 커서가 있고 아무 일도 일어나지 않으면 서버가 잘 켜저 있는 것
      • 왜 아무것도 안 보일까? 아직 우리가 만든 서버에 접속한 사람이 없기 때문
      • 웹 브라우저에 localhost:3000 입력하면 console.log()가 잘 작동하는 걸 확인 가능

        - 주소창 엔터 칠 때마다 나옴 → 이벤트 기반: 사용자가 방문하면 출력한다

  • 왼쪽과 오른쪽은 서로 다른 공간임
    • IP는 같지만 → 동일한 한 대의 컴퓨터
    • 포트 번호가 다름: 동일 컴퓨터 내에서 포트 번호는 절대 중복되면 안 됨
  • 왼쪽과 오른쪽은 서로 데이터를 주고받을 수 있음 (통신 가능)
    • 같은 집(컴퓨터)에서 방 번호만 다른 거니까
    • 집이 다르면 데이터를 보낼 수 없음 → 누구나 들어올 수 있는 공용 공간을 만들어 해결: 도메인(domain) → 공용 ip를 사서 누구나 올 수 있게 만듦
  • 왜 웹 브라우저에 아무것도 안 뜰까? (client 입장)
    • 접속과 통신은 다 됐는데 응답이 없기 때문 (response를 설정하지 않았음)
  • 서버 프로그램의 특징
    • 수정 내용이 있다면 서버를 껐다가 다시 켜 주어야 함
      • 서버 종료: ctrl + C
    • 서버를 제작할 때는 반드시 포트 번호를 지정한다. (중복 X)
    • 서버에서 코드를 수정하는 경우에는 반드시 서버를 정지하고 작업한다. → 대규모 서버는 껐다 켜는 데 10분씩 걸리기도 함
  • 필수: 서버를 생성할 때 매개 변수 2개 필요 → 순서를 반드시 지켜야 함
    • req → 사용자가 보낸 모든 데이터가 담기는 공간 (ip, data, 접속환경, …)
    • res → 서버가 사용자에게 보낼 데이터를 담는 곤강
    • 주의점: 이름은 자유롭게 적어도, 순서는 반드시 지켜야 한다.(req,res)

2. req

서버를 열어서 내 컴퓨터에 접속한 사람의 ip를 출력해보기

  1. 서버 만들기: const http = require("http");
  2. 틀 만들기
    • 위와 같이 틀을 먼저 짜고 이후 내용 작성!
  3. ip 체크하기: 모듈 설치
    • ip를 체크하는 모듈을 가져와야 함: request-ip
      • 모듈이 없을 때는 반드시 설치 후 사용
      • npm i request-ip 명령어로 설치하기

설치가 안 돼요😭

  • 보안상 막아놓았기 때문
  • 해결 방법: powershell 관리자 권한으로 실행 → Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned 복사 → powershell 창에서 마우스 우클릭 → Get-ExecutionPolicy -List 확인

    CurrentUser가 RemoteSigned인 걸 확인 후 vscode로 돌아가서 다시 설치해보면 잘 됨
  1. ip 체크하기: ip 가져오기
    • 터미널에서 서버 켜기 → 웹 브라우저에서 localhost:3000 접속하기 → 터미널에 포트 번호 3000번으로 접근한 사람에 대한 접속 정보가 출력되는 걸 확인 가능
    • 확인했으면 서버 끄고 아래와 같이 코드 수정해 ip 받아오기
      let ip = req_ip.getClientIp(req);
      console.log(ip);
      • 내가 나한테 접근한 거라서 1만 나옴



Ⅱ. 오후 수업

LangChain 공식 문서

A. 4교시: LangChain

1. 지난 시간 복습

  • 제로샷 프롬프팅(Zero-Shot Prompting)
    • 사전 예시 없이, 단순 요청에 모델이 답변을 생성하는 방식
    • 특징
      • 모델은 오로지 내가 지정해 준 프롬프트 템플릿에 포함된 정보만을 기반으로 응답을 생성
    • 장점
      • 빠르고(→프롬프트만 보고 답변하기 때문), 간단하게 적용 가능
    • 단점
      • 복잡한 문제나 구체적인 형식을 요구하는 작업에서는 모델의 응답이 기대에 못 미칠 수 있음 → 프롬프트 템플릿 내에서 복잡한 문제나 구체적인 형식을 전부 구현하는 건 어렵기 때문
    • 개선 방법
      • Few-Shot Prompting 사용 → 약간의 예시를 줘서 학습시키기
      • memory 기능 사용: 피드백을 통한 개선된 응답
      • 체인 결합: 여러 개의 모델을 연결
      • RAG: 검색 증강 생성 → 대규모 언어 모델(LLM)의 답변 생성 과정에 외부 검색 기술을 결합하여, 학습된 데이터뿐만 아니라 최신 또는 특정 분야의 외부 지식 소스에서 관련 정보를 검색해 답변의 정확성과 신뢰성을 높이는 기술

2. Zero-Shot Prompting 정리

  • 단순 프롬프트를 통해 LLM 모델에게 결과를 응답받는 방법
  • 다섯 가지 단계 기억하기
    1. 모델 생성
      • llm_model = ChatOpenAI(model_name="gpt-4o-mini", temperature=0, max_tokens=500)
    2. 아웃풋 파서 생성
      • str_output = StrOutputParser()
    3. 프롬프트 생성
      • prompt = ChatPromptTemplate.from_template("{words}를 영어로 번역해 주세요.") : 단순 템플릿 지정
      • role, human, ai 메시지를 지정해주는 내용을 작성할 때는 .from_messages 사용
    4. 체인 생성
      • chain = prompt | llm_model | str_output
    5. 체인 실행
      • result = chain.invoke({"words": "사느냐 죽느냐 그것이 문제로다. 가혹한 운명의 화살과 돌멩이를 견디는 것 또는 고난의 바다에 무기를 들고 맞서는 것, 어떤 것이 더 고귀한가?"})
      • print(result): String 출력 파서를 사용했기 때문에 그냥 print하면 됨
        → "To be or not to be, that is the question. Whether 'tis nobler in the mind to suffer the slings and arrows of outrageous fortune, or to take arms against a sea of troubles and by opposing end them, which is the more noble?"

3. 퓨샷 프롬프팅 (Few-shot Prompting)

  • 몇 가지 예시를 프롬프트에 포함시켜 모델에게 원하는 출력 형식이나 해결 방식을 학습시키는 방식
  • 특징
    • 예시를 제공하여 모델이 어떤 방식으로 답변해야 하는지 안내
    • 응답의 일관성과 정확도를 향상
  • 장점
    • 구체적으로 모델이 수행해야할 작업에 대해 인지시켜 원하는 결과를 얻을 수 있음
  • 단점
    • 적절한 예시 선택을 하지 못하면 잘못된 결과를 얻을 수 있음, 프롬프트가 길어질 수 있음

입력된 데이터의 반대말을 출력

from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate, FewShotPromptTemplate, PromptTemplate
from langchain_core.output_parsers import StrOutputParser

# 예시
examples1 = [
    {"input": "happy", "output": "sad"}
    , {"input": "tall", "output": "short"}
    , {"input": "sunny", "output": "rainy"}
    , {"input": "surprised", "output": "calm"}
    , {"input": "dry", "output": "humid"}
    , {"input": "hot", "output": "cold"}
    , {"input": "satisfied", "output": "dissatisfied"}
]

# 모델: 앞서 사용한 llm_model 그대로 사용

# 예시 데이터 표현을 위한 기본 템플릿 생성
prompt = PromptTemplate.from_template("입력: {input} \n 출력: {output}")
  • 주의: 예시 데이터 표현을 위한 기본 템플릿에 ChatPromptTemplate 사용 X
    • FewShotPromptTemplate은 메시지 리스트로 동작하지 않아 ChatPromptTemplate 사용 시 구조적 불일치가 발생 → 오류 출력
      • AttributeError: 'ChatPromptTemplate' object has no attribute 'get'
    • 기본 프롬프트 템플릿(PromptTemplate) 써야 함!
# 퓨샷 프롬프트 템플릿 생성
fewshot_prompt = FewShotPromptTemplate(
    examples=examples1
    , example_prompt=prompt
    , prefix="""입력의 반대말을 출력합니다.
    반드시 사전에 등장하는 반대말만 출력하세요.
    사전에 반대말이 존재하지 않으면 반대말이 없다고 출력해 주세요."""
    , suffix="입력: {input}" # 전체 프롬프트 마지막에 추가되는 텍스트
    , input_variables=["input"] # 퓨샷 프롬프트 탬플릿에서 사용되는 입력 변수
)
  • 그외 FewShotPromptTemplate 파라미터
    • example_separator="\n\n"
      • 예시 사이에 추가되는 구분자
# 체인 연결
chain = fewshot_prompt | llm_model | str_output
# 체인 실행
chain.invoke({"input":"어둡다"})
출력: 밝다
  • prefix: 전체 프롬프트 앞쪽에 추가될 설명문
  • suffix: 전체 프롬프트 마지막에 추가되는 텍스트. 어떤 값으로 입력을 해야 하는지를 작성해 주는 부분
  • FewShotPromptTemplate은 내부적으로 일반 텍스트 프롬프트를 구성하는 데 최적화되어 있음
    • 텍스트 기반 프롬프트를 생성, 예시(example)들을 단순 텍스트 블록으로 삽입
    • 예시를 단순 문자열 템플릿으로 정의하고 조합하는 구조 →
    • FewShotPromptTemplate과 ChatPromptTemplate을 같이 쓰면 내부 구조 충돌 및 예상치 않은 동작이 생길 수 있음
      • 둘은 서로 다른 프롬프트 구조를 요구하므로 함께 사용할 수 없음
      • ChatPromptTemplate: 역할(role)-기반 메시지(예: system, user, assistant)를 포함하는 채팅형 프롬프트를 생성. 채팅 메시지 구조(역할 기반 메시지 목록)를 요구.
  • 프롬프트 템플릿 지정 이유: 입력 값에 따른 출력 값 형식 지정 (형식 내용)
  • examples: 어떤 식으로 반대말 데이터를 출력해줄지에 대한 내용

B. 5교시: LangChain

1. 퓨샷 프롬프팅 (cont.)

  • 프롬프트 내용을 바꿔가며 모델 출력 확인해보기
    1. "입력의 반대말을 출력한다."
      • 반대말 관계가 아닌 단어들도 출력에 나옴 (문법적 반대말이 아닌 사람들이 반대말로 느끼는 단어, 비교 대상으로 자주 등장하는 단어를 출력하는 듯함)
      • 예: 여름 - 겨울, 프랑스 - 독일, 미국 - 중국, 트럼프 - 바이든, …
      • 프롬프트 내에서 명확하게 단어의 범위를 지정해줄 필요가 있음
    2. "입력의 반대말을 출력한다. 반드시 사전에 등장하는 반대말만 출력한다. 정치, 인물 등 민감한 단어들은 출력하지 않는다."
    3. "입력의 반대말을 출력하고 반드시 일상에서 쓰는 반대말만 출력하면서 사전에 없다면 '알수없음'이라고 출력하세요"
      • 1번과 동일한 입력을 넣었을 때 여름-겨울 제외하고 모두 기대한대로 알수없음으로 처리됨

복잡한 질문에 대한 단계별 답변 구성

  • 상품명을 입력 받아 홈쇼핑 대본을 자동으로 생성하는 서비스
# 예시
examples2 = [
    {
        "question": "상품명: '에어프라이어', 특징: '간편 조리, 1300W 출력', 가격: '120,000원'일 때 단계별 대본 가이드 예시를 보여주세요.",
        "answer": (
            "1) 인사 및 상품 소개: \"안녕하세요 여러분! 오늘은 집에서 간편하게 튀김 요리를 할 수 있는 '에어프라이어'를 소개합니다!\"\n"
            "2) 주요 특징 설명: \"1300W의 강력한 출력으로 바삭함을 살려주고, 조리 시간이 단축됩니다.\"\n"
            "3) 사용 시나리오 제시: \"감자튀김, 치킨너겟, 채소구이까지 모두 간편하게 조리해보세요.\"\n"
            "4) 가격 및 혜택 안내: \"지금 구매하시면 120,000원에 무료 배송과 1년 무상 A/S가 제공됩니다.\"\n"
            "5) 콜 투 액션: \"아래 구매 버튼을 눌러 할인 혜택을 놓치지 마세요!\""
        )
    },
    {
        "question": "상품명: '블루투스 헤드폰', 특징: '노이즈 캔슬링, 20시간 배터리', 가격: '80,000원'일 때 단계별 대본 가이드 예시를 보여주세요.",
        "answer": (
            "1) 인사 및 관심 유도: \"안녕하세요! 오늘은 음악 감상에 최적화된 '블루투스 헤드폰'을 소개드립니다.\"\n"
            "2) 기능 강조: \"능동형 노이즈 캔슬링으로 외부 소음을 완벽 차단, 최대 20시간 배터리로 하루 종일 사용 가능해요.\"\n"
            "3) 데모 시연 제안: \"실제 사용해볼까요? 소음 많은 카페에서도 깨끗한 사운드를 경험해보세요.\"\n"
            "4) 특별 할인 안내: \"오늘 한정 5% 할인 쿠폰 코드: LIVE5 적용하세요!\"\n"
            "5) 구매 유도 문구: \"지금 바로 구매 버튼을 클릭하고, 편안한 음악 시간을 즐겨보세요!\""
        )
    }
]
  • Question을 입력 데이터라고 생각하면 됨
  • 주의: 퓨샷 프롬프트에 넣는 예시는 토큰으로 인식됨 → 예시를 많이 넣으면 토큰 소모량(비용) 증가할 수 있음
# 예시용 프롬프트 템플릿 생성 → 단순 프롬프트 템플릿 사용
prompt = PromptTemplate.from_template("Q: {question} \n A: {answer}")

# 퓨샷 프롬프트 템플릿 생성
fewshot_prompt = FewShotPromptTemplate(
    examples=examples2
    , example_prompt=prompt
    , prefix="구어체로 답변해 주세요."
    , suffix="Q: {input} \n A:"
    , input_variables=["input"] 
)

# 체인 구성 및 호출
chain = fewshot_prompt | llm_model | StrOutputParser()
res = chain.invoke({"input": "상품명: '무선 진공청소기', 특징: '강력 흡입, 30분 연속 사용', 가격: '200,000원'일 때 단계별 대본 가이드 예시를 보여주세요."})
print(res)
  • example_prompt: 예시 데이터(문자열)를 프롬프트 형태로 구성하는 템플릿
  • prefix: 전체 프롬프트 앞쪽에 추가될 설명문
    • 생략 가능
    • 보완 역할 / 행동지침
  • prefix, suffix 사이에 examples가 "Q: {question} \n A: {answer}" 형태로 들어감
  • suffix는 실제 사용자의 값이 들어왔을 때 예시용 프롬프트와 동일한 형식으로 나올 수 있도록 하는 신호
    • 'A:' 뒤의 {answer}는 GPT가 줄 것이기 때문에 빼고 주기 ('A 뒤를 채워줘'라는 신호)
    • 사용자의 입력에 대한 값
  • nput_variables: 퓨샷 프롬프트 탬플릿에서 사용되는 입력 변수
# 체인 구성 및 호출
chain = fewshot_prompt | llm_model | StrOutputParser()
res = chain.invoke({"input": "상품명: '무선 진공청소기', 특징: '강력 흡입, 30분 연속 사용', 가격: '200,000원'일 때 단계별 대본 가이드 예시를 보여주세요."})
print(res)
1) 인사 및 상품 소개: "안녕하세요 여러분! 오늘은 집안 청소를 혁신적으로 바꿔줄 '무선 진공청소기'를 소개합니다!"

2) 주요 특징 설명: "이 청소기는 강력한 흡입력으로 먼지와 이물질을 쉽게 제거해주며, 30분 동안 연속으로 사용할 수 있어요. 무선이기 때문에 이동이 편리하고, 어떤 공간에서도 자유롭게 사용할 수 있습니다."

3) 사용 시나리오 제시: "거실, 주방, 심지어 자동차 안까지! 다양한 장소에서 손쉽게 청소해보세요. 바닥은 물론 카펫과 소파까지 완벽하게 청소할 수 있습니다."

4) 가격 및 혜택 안내: "지금 구매하시면 200,000원에 무료 배송과 2년 무상 A/S가 제공됩니다. 또한, 첫 구매 고객에게는 추가 청소 도구 세트를 드립니다!"

5) 콜 투 액션: "지금 바로 아래 구매 버튼을 클릭하고, 집안 청소의 새로운 경험을 시작해보세요! 놓치지 마세요!"
  • 어차피 예시를 주는데 prefix는 왜 주나요?
    • 관습이냐 명확한 규율이냐의 차이 → examples은 규칙에 가까움, prefix는 지침에 가까움
      • 예시는 확실하게 해당 데이터를 학습해 그대로 추출하게 해 주는 역할
      • prefix는 예시만으로는 다 나타낼 수 없는 부분을 언어로 가이드라인을 제공

2. ExampleSelector

  • 제공하는 예시가 많을수록 토큰 사용량이 많아지며 사용료가 많이 나오게 됨
  • 예시를 많이 주되 사용자의 입력과 유사한 예시 한두 개만을 선택하여 예시로 사용하는 것
    • 매번 많은 예시를 다 학습하면 토큰이 많이 사용되는 점을 보완하기 위함
  • 예시와 사용자의 입력에 텍스트 임베딩(Text Embedding)을 진행하여 코사인 유사도가 가장 높은 k개의 예시를 선택하여 사용: SemanticSimilarityExampleSelector
    • 워드 임베딩이 추가됨 → 내 데이터와 예시 데이터의 유사도를 확인하며 질문의 의도와 가까운 예시를 선택
  • Vector DB 종류도 다양함: Chroma, FAISS 등
# 입력과 예시의 코사인 유사도를 계산
from langchain.prompts.example_selector import SemanticSimilarityExampleSelector

# 텍스트 임베딩: 텍스트 데이터를 벡터화하는 과정(수치화)
from langchain_openai import OpenAIEmbeddings

# 수치화한 벡터 데이터를 저장하는 저장소 → 유사도를 비교하는 알고리즘도 제공
from langchain.vectorstores import FAISS

# 첫 번째 예시: 회의록 작성, 두 번째 예시: 요약
examples3 = [
    {
        "input": (
            "2023년 12월 25일, XYZ 회사의 마케팅 전략 회의가 오후 3시에 시작되었다. "
            "회의에는 마케팅 팀장인 김수진, 디지털 마케팅 담당자인 박지민, 소셜 미디어 관리자인 이준호가 참석했다. "
            "회의의 주요 목적은 2024년 상반기 마케팅 전략을 수립하고, 새로운 소셜 미디어 캠페인에 대한 아이디어를 논의하는 것이었다. "
            "팀장인 김수진은 최근 시장 동향에 대한 간략한 개요를 제공했으며, 이어서 각 팀원이 자신의 분야에서의 전략적 아이디어를 발표했다."
        ),
        "answer": (
            "회의록: XYZ 회사 마케팅 전략 회의\n"
            "일시: 2023년 12월 25일\n"
            "장소: XYZ 회사 회의실\n"
            "참석자: 김수진 (마케팅 팀장), 박지민 (디지털 마케팅 담당자), 이준호 (소셜 미디어 관리자)\n\n"
            "1. 개회\n"
            "   - 김수진 팀장의 개회사\n"
            "2. 시장 동향 개요 (김수진)\n"
            "   - 최근 시장 동향 분석\n"
            "3. 디지털 마케팅 전략 (박지민)\n"
            "   - SEO 최적화 및 온라인 광고 방안\n"
            "4. 소셜 미디어 캠페인 (이준호)\n"
            "   - 인플루언서 마케팅 제안\n"
            "5. 종합 논의\n"
            "   - 예산 및 자원 배분\n"
            "6. 마무리\n"
            "   - 다음 회의 일정 및 회의록 배포 담당자 지정"
        )
    },
    {
        "input": (
            "이 문서는 '지속 가능한 도시 개발을 위한 전략'에 대한 20페이지 분량의 보고서입니다. "
            "보고서는 지속 가능한 도시 개발의 중요성, 현재 도시화의 문제점, 그리고 지속 가능한 개발 전략을 다루고 있습니다. "
            "여러 국가의 성공 사례와 얻은 교훈도 포함되어 있습니다."
        ),
        "answer": (
            "문서 요약: 지속 가능한 도시 개발 전략 보고서\n\n"
            "- 중요성: 사회적·경제적·환경적 이점 강조\n"
            "- 문제점: 환경 오염, 자원 고갈, 불평등 분석\n"
            "- 전략: 친환경 건축, 대중교통 개선, 에너지 효율성 증대\n"
            "- 사례 연구: 코펜하겐, 요코하마 성공 사례\n"
            "- 교훈: 다각적 접근, 지역사회 협력, 장기 계획 필요"
        )
    }
]
  • ExampleSelector는 Few-Shot Prompting 내에 들어 있는 기능 중 하나
    • ExampleSelector를 만든 후 Few-Shot Prompt 안에 넣어야 함
# 유사도 비교 후 샘플을 선택하는 클래스 생성
example_selector = SemanticSimilarityExampleSelector.from_examples(
    examples3  # 유사도 검사를 진행할 예시 데이터
    , OpenAIEmbeddings() # 임베딩 도구
    , FAISS #저장소
    , k=1 # 선택할 예시 개수
)

# 예시 데이터를 프롬프트로 변경해주는 프롬프트 템플릿
prompt = PromptTemplate.from_template(
    """
    문서: {input}

    결과: {answer}
    """
)

# 퓨삿 프롬프트 템플릿
fewshot_prompt = FewShotPromptTemplate(
    example_selector = example_selector
    , example_prompt = prompt
    , prefix = "입력된 문서에 대해 적절한 형식으로 데이커를 생성하세요"
    , suffix = "문서 : {input} \n 결과:"
    , input_variables = ["input"]
)
  • 이전 프롬프트 템플릿과 비교해보기
# 체인 연결
chain = fewshot_prompt | llm_model | str_output
# 체인 호출
rs = chain.invoke({
    "input": (
        "2025년 5월 20일 오후 4시부터 약 90분간, 서울 본사 3층 대회의실에서 "
        "신제품 출시 킥오프 회의가 진행되었습니다. 회의에는 개발팀장 김민준, "
        "디자인팀장 이지은, 영업팀장 박성호, 마케팅팀장 오세훈, 품질관리 담당 최유리가 참석했으며, "
        "주요 안건은 제품 디자인 확정, 출시 일정, 마케팅 채널 전략, 리스크 관리 방안이었습니다."
    )
})
print(res)
회의록: 신제품 출시 킥오프 회의  
일시: 2025년 5월 20일 오후 4시  
장소: 서울 본사 3층 대회의실  
참석자: 김민준 (개발팀장), 이지은 (디자인팀장), 박성호 (영업팀장), 오세훈 (마케팅팀장), 최유리 (품질관리 담당)

1. 개회  
   - 김민준 팀장의 개회사

2. 제품 디자인 확정 (이지은)  
   - 최종 디자인안 발표 및 논의

3. 출시 일정 (박성호)  
   - 제품 출시 일정 및 단계별 계획

4. 마케팅 채널 전략 (오세훈)  
   - 마케팅 채널 및 캠페인 계획

5. 리스크 관리 방안 (최유리)  
   - 잠재적 리스크 분석 및 대응 방안

6. 종합 논의  
   - 각 팀의 의견 수렴 및 조율

7. 마무리  
   - 다음 회의 일정 및 회의록 배포 담당자 지정
rs = chain.invoke({
    "input": (
        "이 문서는 '머신러닝 모델 성능 최적화 기법'에 대한 15페이지 분량의 기술 보고서입니다. "
        "보고서는 하이퍼파라미터 튜닝(그리드 서치, 베이지안 최적화), 데이터 증강(회전·크롭·색상 보정), "
        "앙상블 기법(배깅·부스팅·스태킹), 모델 경량화(지식 증류·양자화), 성능 평가(Accuracy·Precision·Recall·F1) 등을 상세히 다룹니다."
    )
})

print(rs)
문서 요약: 머신러닝 모델 성능 최적화 기법 보고서

- 하이퍼파라미터 튜닝: 그리드 서치, 베이지안 최적화 방법 설명
- 데이터 증강: 회전, 크롭, 색상 보정 기법 소개
- 앙상블 기법: 배깅, 부스팅, 스태킹 기법의 장단점 분석
- 모델 경량화: 지식 증류, 양자화 기법의 적용 및 효과
- 성능 평가: Accuracy, Precision, Recall, F1 스코어의 정의 및 활용 방법

C. 6교시: LangChain

1. Callbacks: 스트리밍(Streaming)

  • 스트리밍: 입력에 대해 답변을 실시간으로 출력
    • 글자가 '흐른다' → 모델 프로세스 완료 후 한 번에 출력되는 것이 아닌 생성 중인 토큰을 실시간으로 출력
    • 챗봇 형태이기 때문에 사용하는 것
      • 진짜 대화하는 느낌을 줌
      • 긴 답변일 경우 답변 중간 답변 내용이 마음에 들지 않으면 중단하고 다시 새로운 질문을 할 수 있도록 해주기 위함 → "실시간성"
  • 완전한 응답이 생선되기 전 생성 중인 결과를 실시간으로 출력
    • 모델 객체 생성 시 포함: StreamingStdOutCallbackHandler()
  • 퓨샷 프롬프팅 + 스트리밍
    1. 프롬프트 탬플릿 영역
      • 예시
      • 예시 프롬프트 템플릿: 예시를 프롬프트화함
      • 퓨샷 트폼프트 템플릿: 예시 프롬프트 템플릿 결과와 입력 데이터를 결합해주는 역할
    2. 핸들러 & 모델 생성 영역
      • 핸들러 객체 생성
      • 핸틀러를 포함한 모델 객체 생성
    3. 체인 생성 영역
      • 체인 생성
      • 체인 호출
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler

# 퓨샷 프롬프팅을 통한 결과 확인
# 예시
examples4 = [
    {"input" : "Agent",           "output" : "프롬프트를 통해 도구를 호출하며 워크플로우를 제어할 수 있는 자동화 컴포넌트"}
    , {"input" : "Chain",           "output" : "여러 프롬프트와 모델 호출을 순차적으로 연결해 파이프라인을 구성하는 구조"}
    , {"input" : "PromptTemplate",  "output" : "입력 변수를 포함해 모델에 보낼 프롬프트 형식을 정의하는 클래스"}
]

# 예시 프롬프트 템플릿
prompt = PromptTemplate.from_template("키워드: {input} \n 설명: {output}")

# 퓨샷 프롬프트 템플릿
fewshot_prompt = FewShotPromptTemplate(
    examples = examples4
    , example_prompt = prompt
    , prefix = "입력된 키워드에 대해 다음 예시처럼 설명하세요."
    # '다음'이라는 말이 가능한 이유: prefix + prompt + suffix순으로 텍스트가 연결되기 때문
    , suffix = "키워드: {input} \n 설명: "
    , input_variables = ["input"]
)
# 핸들러 객체 생성
stream_handler = StreamingStdOutCallbackHandler()
# 핸들러가 포함된 모델 객체 생성
stream_model = ChatOpenAI(
    model_name="gpt-4o-mini"
    , temperature = 0
    , streaming = True
    , callbacks = [stream_handler]
)
  • 여기서 StreamingStdOutCallbackHandler()는 토큰이 생성될 때마다 콘솔에 실시간으로 결과를 출력해줌

callbacks 파라미터

  • Callbacks to add to the run trace. (default는 None)
    • callbacks 파라미터는 추가적으로 원하는 동작이 있을 때만 명시적으로 넣어주는 선택적 요소
  • 모델 객체를 생성할 때 사용
  • 모델의 실행 과정 중 특정 이벤트가 발생할 때 자동으로 추가 작업을 수행할 수 있도록 해주는 함수(혹은 객체)들의 목록을 지정하는 역할
    • 모델이 동작하는 중간과정에 추가 동작(로깅, 스트리밍 출력, 체크포인트 저장 등)을 자동화·확장해주는 역할
  • LangChain 및 딥러닝 프레임워크에서의 callbacks 역할
    • 실행 중간 상태 모니터링: 모델이 예측/추론/스트리밍할 때, 중간 결과나 토큰 생성, 에러 발생 등 다양한 이벤트를 실시간으로 감지해서, 이를 콘솔에 출력하거나 별도로 저장/로깅/시각화합
    • 자동화 및 로깅: 학습 중 체크포인트 저장, EarlyStopping(성능 개선 없으면 멈춤), TensorBoard 시각화 등의 다양한 자동화 기능을 구현할 때 사용
    • 사용자 정의 콜백 구현 가능: 콜백을 직접 만들어서, 필요한 이벤트에 맞춰 코드를 실행
  • 콜백 핸들러가 없을 때
    • 특별한 이벤트 처리 없이, 모델의 가장 기본적인 반환값(결과만) 받아서 사용
# 체인 생성
chain = fewshot_prompt | stream_model | StrOutputParser()
# 체인 호출
res=chain.invoke("example_selector")
print(res)
키워드: example_selector  
설명: 주어진 입력에 가장 적합한 예제를 선택하여 모델의 응답 품질을 향상시키는 기능 또는 컴포넌트.키워드: example_selector  
설명: 주어진 입력에 가장 적합한 예제를 선택하여 모델의 응답 품질을 향상시키는 기능 또는 컴포넌트.

왜 두 번 출력되지?

  • StreamingStdOutCallbackHandler는 응답을 생성하는 즉시 터미널(콘솔)에 한 번 출력함
  • 그런데 지금 우리는 체인에 'StrOutputParser()'가 붙어 있고 print()로 출력도 하고 있음 → chain.invoke()의 결과(예: res.content)를 또 print하면, 똑같은 답이 한 번 더 표준출력에 표시됨
    • 즉, 한 번은 스트리밍 콜백으로, 한 번은 후처리 print로 중복 출력
  • 실시간 스트리밍이 중요하다면, chain.invoke() 후 따로 res.content를 print하지 않아야 함!
    • StreamingStdOutCallbackHandler를 사용하면 모델이 생성하는 토큰들을 실시간으로 콘솔에 출력해 줍니다. 그런데 여기서 print(res.content)를 함께 쓰면, 스트리밍 출력과 함께 결과가 한 번 더 출력되어 두 번 나오는 겁니다.
      • chain.invoke() 결과 (res)는 모델 응답을 담고 있습니다. 스트리밍 핸들러가 이미 콘솔에 실시간 출력을 하므로, print(res.content)를 하면 최종 결과를 다시 한 번 출력하게 됩니다. 그래서 둘 중 하나만 사용해야 중복 출력이 안 됩니다.
상황코드 실행 방식출력 방식
스트리밍 출력 필요 시StreamingStdOutCallbackHandler를 쓰고, print(res.content)는 하지 않음토큰 단위 실시간 출력됨
최종 결과만 단 한 번 보고 싶을 때스트리밍 핸들러 빼고 streaming=False, print(res.content) 사용완성된 결과 한 번 출력
# 체인 생성
chain = fewshot_prompt | stream_model
# 체인 호출
res=chain.invoke("example_selector") # 이 호출시 토큰 하나씩 실시간 출력됨

# stream_handler만 사용한다면, print(res)를 호출하지 않아야 함
# print(res) 하면 한 번은 핸들러로 스트리밍, 한 번은 최종 결과 전체 출력을 해서 총 두 번 출력됨
# StreamingStdOutCallbackHandler를 사용하면 실시간 출력도 같이 되고, invoke() 자체도 출력 결과를 반환하기에 중복 출력이 발생
  • StreamingStdOutCallbackHandler를 콜백으로 설정한 상태에서 chain.invoke()를 호출하면, 그 함수가 반환되기 전에 내부적으로 스트리밍 핸들러가 실시간으로 토큰을 콘솔에 출력해 줍니다. 따라서 반환값인 res를 다시 호출하거나 print하지 않아도, 스트리밍 출력은 이미 실행 중에 나타납니다.
    • res 변수는 여전히 최종 결과를 담고 있어서 필요할 때 내부 내용 접근 가능하지만,
    • 스트리밍 출력은 invoke() 호출 시 콜백 핸들러가 자동으로 수행합니다.
    • 따라서 스트리밍 출력 확인에 res를 다시 호출하거나 print할 필요가 전혀 없습니다. 이게 스트리밍 핸들러 사용 시 중복 출력 없이 실시간 출력 보는 표준적인 방법입니다.
  • 다른 핸들러도 있음: FinalStreamingStdOutCallbackHandler
    • StreamingStdOutCallbackHandler → 중복 표출(토큰마다, 결과)
      • 토큰 생성 시마다 실시간으로 바로 표준출력에 출력
      • 코랩의 출력 셀은 실시간 출력이 제한적이나, 토큰별 출력을 여러 번 발생시키면서 출력 업데이트를 어느 정도 압축해 표시하므로 어느 정도 스트리밍 효과가 있음
    • FinalStreamingStdOutCallbackHandler → 한 번만(최종 결과)
      • 토큰을 내부적으로 버퍼링 후, 최종 완성된 응답이 완성되는 시점에 한 번만 출력
      • 콘솔 환경에서 실행해야 streaming 출력이 정상적으로 작동
      • Jupyter 등에서는 streaming 출력이 제대로 안 될 수 있음
  • 코랩의 출력 셀은 표준 터미널 콘솔 환경과 달리 즉각적인 표준출력 스트림 반영이 제한적이기 때문에 StreamingStdOutCallbackHandler로 하는 실시간 토큰 스트리밍 출력이 제대로 작동하지 않는 경우가 많음
    • StreamingStdOutCallbackHandler는 코랩 환경에서 토큰 단위로 표준출력에 실시간으로 출력하는 구조라, 코랩 셀에서 어느 정도 작동할 수 있습니다. 반면, FinalStreamingStdOutCallbackHandler는 스트리밍 도중 중간 토큰 출력 없이 최종 결과만 한 번에 출력하도록 설계된 핸들러라서 코랩 셀의 출력 뷰 특성상, 스트리밍 효과가 전혀 없으며, 최종 결과가 한꺼번에 출력되고 결과적으로 "스트리밍이 안 되는 것처럼" 보이게 됩니다.
      • 코랩처럼 출력이 버퍼링되고 묶여서 출력되는 환경에서 스트리밍 효과가 실질적으로 구현되지 않음
  • 별도 print(res) 없이도 한 번만 결과가 표출됨




Ⅲ. CARRER UP

미니 프로젝트 전체 발표

2반: 대화 시뮬레이션 게임

  • 이성과의 대화 경험 부족 → 관계 형성 어려움 사례
    • 불안감, 잦은 실수, 자신감 하락
  • 이성과의 대화 및 상황 대처를 반복적으로 연습할 수 있는 서비스 제공
    • 긍정적인 상호작용 패턴 학습
    • 안전한 연습 공간 제공
  • 소통 능력 개발
    • 일방향(유튜브 강의, 책) 학습으로는 한계 존재
      • 피드백 부재, 지루함, 낮은 동기 등
      • 소통 능력은 반복 훈련이 필수적인 실전 기술인데 일방향 학습에서는 훈련을 하려면 현실에서 다른 누군가에게 말을 해야함 → 용기가 없으면 하기가 힘듦
  • 이상적인 소통 훈련 환경 → "게임"
    • 안전한 실패 환경
    • 즉각적 피드백
    • 자발적 반복 학습
  • 연구로 증명된 '게임'의 효과
    • 효과 크기 g: 게이미피케이션이 전통 교육 방식에 비해 얼마나 더 효과적인지를 나타내는 수치
    • 문제 해결 능력 향상 (g=0.87, 큰 효과)
      • A Meta-Analysis on the Effects of Serious Games on Problem-Solving Skills (Lu et al., 2023)
    • 동기 부여 및 참여도 (g=0.4-0.44, 중간 효과)
      • The Impact of Game-Based Learning on Child Development (Alotaibi, 2024)
    • 정서 및 사회성 발달 (g=0.35-0.38, 중간 효과)
      • The Impact of Game-Based Learning on Child Development (Alotaibi, 2024)
    • 실질적 학습 성과
      • Effects of Game-Based Learning on Student Achievement (Cheung & Ng, 2021)
  • 기술 스택
    • HTML, CSS, JavaScript
    • Flask, SQLite, SQLAlchemy
  • 감성/톤 분석 활용
    • LLM 모델을 사용해 입력한 문장에 따른 4개의 답변을 분석하고 감정 분석 → 긍정적인 감정 문장은 게임 상에서 호감도 점수 크게, 부정적인 감정 문장은 호감도 점수 마이너스로
    • 1차 감정 추론: Transformers + PyTorch 활용
      • daekeun-ml/koelectra-small-v3-nsmc 모델
    • 후처리 보정: 표면 부정어에 과민한 문제
      • 긍정 의도를 부정으로 찍는 문제에 대해 각 지원 표현(예: 빌려주다, 감사, 고마워, 사과, 제안 등)의 가중치를 향상시켜 문장에 대한 의미 파악
    • 톤 분류
      • MoritzLaurer/mDeBERTa-v3-base-mnli-xnli(멀티링구얼 NLI)을 사용한 톤 분류

3반: Vision Transformer를 활용한 DeepFake 이미지 분류

  • DeepFake: 실존 인물을 대상으로 생성형 인공지능을 이용해 실제처럼 보이도록 조작, 생성된 모든 자료를 통칭
  • 사용 모델: CLIP, DINO, ViT
    1. CLIP + GNN
      • CLIP: 이미지+텍스트 동시 학습하여 두 데이터 유형 간의 연관성을 이해하는 대규모 멀티모달 모델 (OpenAI 개발)
      • GNN: 그래프 형태의 데이터를 처리하는 인공 신경망
    2. DINOv2
      • Meta AI가 개발한 차세대 자기지도학습 모델
    3. ViT
      • Transformer 구조를 이미지에 적용한 대표 모델
      • 이미지 전체의 문맥 고려

4반: 한국 면 요리 분류

  • 환경 및 툴 구성
    • EDA: Python, NumPy
    • 전처리: VISIPICS, YOLO v8, roboflow
    • 모델링 및 평가: PyTorch, Matplotlib, YOLO11, Scikitlearn
    • 서비스 구현: Streamlit
  • 문제 정의 및 해결
    • VGG16과 같은 분류 모델 → 이미지 전체에 대해 단일 라벨을 할당 → 한 장의 이미지에 여러 음식이 있는 복합적인 상황에서는 정확한 분석이 불가능
    • 따라서 객체 탐지(Object Detection) 기술을 도입해 해결

5반: 제주 관광 특화 글로벌 챗봇 서비스

  • AI Hub: 국내 여행로그 데이터
    • 총 8개의 DB 테이블
    • 소비금액 총합 분석
      • 상관 관계 높은 feature 분석 및 시각화
      • 이상치 분석 및 제거
  • 머신러닝 모델 학습 → LightGBM 최종 채택
  • ML 모델 Joblib 추출 → FastAPI 백엔드 서버
  • Frontend에서 feature 선택 → ML로 예측: "예산"
  • 영어 지원
  • LLM 활용 추천 질문 생성
  • Chatbot
    • LLM 모델: A.dot X 72B
    • LangChain: 외부 데이터, 도구, 메모리 연결 → AI-Hub 관광 특화 말뭉치 데이터
    • PostgreSQL: Vector DB 숫자 배열로 저장 → AI-Hub 국내 여행로그 데이터
      • Vector DB는 AI 임베딩(숫자 배열, 벡터)을 효율적으로 저장하고 검색하는 특화된 데이터베이스
      • 이미지, 텍스트, 오디오 등 다양한 데이터를 "숫자 배열(벡터)" 형태로 저장하며, 유사한 데이터를 빠르게 찾는 데 사용됩니다. 검색 방식은 주로 "유사도 기반(ANN 등)"
      • Pinecone, Milvus 등 벡터 데이터베이스 소프트웨어를 통칭하며, 숫자 배열 저장에 특화된 신개념 데이터베이스
    • LangChain, PromptTemplate, VectorData
      • VectorData 구축 과정에서 Web Crawling을 통해 소비, 가게정보 데이터, 로마자 표기법 추가
    • 특정 지역에 대한 질문에 대해 실존하는 식당을 가중치를 통해 추천 가능
      • Vector DB에 들어 있는 증강된 데이터를 즉시 조회하여 제안
    • 대화 내역은 LLM 모델 재학습을 위해 Key Value 형태로 DB 저장 → 파인 튜닝
  • 일정 추천
    • 수학함수와 탐욕 알고리즘 사용
    • 지도 표시를 위한 좌표값 정규화
    • 추천 후보 평가 로직
  • 아키텍처 구조
  • 기술: 시퀀스 다이어그램

6반: 블로그 여행 데이터 기반 AI 여행지 추천 서비스

  • 서비스 흐름도
  • ERD
  • 클래스 다이어그램
  • 시스템 아키텍처
  • 개발 환경
    • 협업 툴: Github, Figma
    • IDE: VS Code
    • Backend: Java 17, Spring Boot, Gradle, Oracle
    • Frontend: React, JavaScript, CSS, HTML, Kakaomap API
  • 핵심 기능
    • 커뮤니티
      • 게시글 생성, 조회, 수정, 삭제 기능
      • 게시글 댓글 작성, 조회, 수정, 삭제 기능
    • 회원 마이페이지
      • 정보 조회, 수정 기능
    • 관리자 페이지
      • 회원 관리, 게시글 관리 기능
    • 세션 기반 인증 처리 → 권한 체크 및 인증정보 주입
    • 여행지
      • 여행지별 계층 카테고리화
      • 여행지 세부정보 표시(이미지, 카카오맵, 주소 등)
  • AI
    • 여행 블로그 크롤링
    • 전처리 및 임베딩
      • 이모티콘 제거
      • 공백 제거
      • 글 청킹: RecursiveCharacterTextSplitter
    • 유저 쿼리 리트리버
    • LLM(리트리버+프롬프트)

7반: 일정 공유 + 시간 조율 캘린더 서비스

  • 통합 플랫폼
    • 게시판, 일정 관리
    • 친구 관리, 실시간 채팅
  • 실시간/비실시간 결합
    • WebSocket 기반 채팅
    • DB 기반 일정/게시판
  • 유저 관계 기반 일정 관리
    • 로그인 사용자 중심
    • 친구와의 겹치는 시간 탐색
  • 확장성 높은 모듈 구조
    • 엔티티/Mapper 분리
    • 기능 추가, 유지보수
  • 기술 스택
  • 주요 기능
    • 내 일정
      • 날짜/시간 일정 등록
      • 일정 추가 시 달력에 자동 등록
      • 달력 날짜 이동 가능
      • 일정 목록에 자동 추가/삭제
    • 친구 일정 및 약속 관리
      • 내 일정에서 입력한 시간 자동 적용 → 친구와 겹치는 비는 시간 탐색
      • 친구 추가 된 친구들의 일정 자동 연동 / 삭제
      • 일정이 겹치는 시간 한 눈에 확인 가능
      • 가장 많이 겹치는 부분 계산
    • 채팅
      • 채팅방 목록
      • 채팅방 CRUD + 비밀번호 설정
      • 채팅/채팅 나가기

8반: 클로바X 개선 핵심 전략 제안


1. 실시간 딜리버리 시장 선점 및 확대

  • 네이버 플레이스 활용
  • 네이버페이 연동
  1. 쿠팡 독점 견제 및 소상공인 경쟁력 강화
  2. 온라인 금융에 대한 높은 수요를 반영해 Clova X와 연계해서 접근성 향상

9반: 부동산 시각화 대시보드

  • 온라인 신문 구독자를 위한 서울시 부동산 시각화 대시보드
  • 활용 데이터: 국토교통부/KB 데이터 허브
    • 서울시 아파트 매매 현황
    • 부동산 관련 정부 정책연형
    • 카카오 디벨로퍼 API

10반: 흉부 X-Ray 사진으로 폐렴환자 구분하기

  • 불균형 데이터셋의 문제
    • 모델이 다수 클래스에 치우쳐 학습할 위험
  • 실제 의료 현상 적합성을 위해 Recall 중심 평가, False Negative 최소화
  • Best Model 탐색: 전이학습(Transfer Learning) 시 학습 층 동결(freezing) 범위에 따라 구분
  • Gran-CAM: 출력 클래스에 기여한 CNN의 활성화 맵을 시각화 → 모델의 판단 근거 확인
    업로드중..




하루 돌아보기

👍 잘한 점

  • 수업 시간 참여 열심히 하고 질문 많이 함
  • 발표 잘 마무리함

👎 아쉬웠던 점

  • AWS, 리눅스 공부 거의 못한 점

🔬 개선점

  • 주말에 공부 많이 하기
profile
2 B R 0 2 B

0개의 댓글