전체 글

전체 글

    [RAG] 문서를 어떻게 잘라 넣을까

    문서를 잘라 넣는 것을 chunking 이라고 한다.단순히 길이를 나누는 것이 아니라 의미 단위로 끊어야 검색이 잘 된다.1. 고정 길이 슬라이싱chunk_size = 500overlap = 100chunks = split_text(text, chunk_size, overlap)문자의 길이를 일정하게 나누어 작은 조각으로 만든다.가장 빠르고 구현이 간단한 방식이다.단순히 길이만 보면 문장이 끊겨 의미가 훼손될 수 있다.구조화된 데이터나 번호가 붙은 목록에서는 잘 작동한다.고정 문자 수 분할은 청크의 문자 수를 제한하는 방법이며, 단어의 길이나 경계를 제어하지 않는다.2. 고정 개수 슬라이싱max_tokens = 512chunks = split_by_token(text, max_tokens)단어 또는 토큰..

    [RAG] 한국어 임베딩 모델 고르기 - 영어 모델로는 왜 안 되나

    영어 모델을 한국어에 쓰면 왜 검색이 안 되나.임베딩은 문장의 의미를 숫자 벡터로 바꾸는 과정이다.1. 임베딩의 기본 원리import org.apache.spark.ml.feature.EmbeddingModel;EmbeddingModel model = new EmbeddingModel();model.setInputCol("text");model.setOutputCol("embedding");model.fit(data);임베딩 모델은 입력 텍스트를 고정된 크기의 벡터로 변환한다.벡터 공간에서 비슷한 의미의 문장은 서로 가까이 위치한다.문장이 가까울수록 코사인 유사도가 높아 검색 결과가 나온다.2. 영어 모델의 한국어 한계String query = "서울 날씨";Vector engVec = englishMo..

    [LLM] LLM 에게 판정을 맡기면 생기는 일 - 맞는 말을 틀렸다고 할 때

    LLM 이라는 것은 대규모 언어 모델이다.사용자의 질문을 받아 문맥에 맞는 답변을 생성한다.1. === 할루시네이션질문: 2024 년 서울 인구수는 몇 명인가?\n모델: 약 980 만명이다.\n사실: 실제 인구는 980 만명이 아니다.모델은 사실과 무관한 내용을 확신 있는 어조로 생성한다.이 현상은 할루시네이션이라고 한다.사실이 아닌 정보를 마치 진실인 것처럼 제시한다.따라서 생성된 내용을 맹신하면 안 된다.2. === 검증 필요성모델 답변: A 법은 2023 년에 개정되었다.\n검증 결과: 해당 법은 2022 년에 개정된 것이다.생성된 답변의 사실 여부를 반드시 확인해야 한다.특히 날짜와 숫자 같은 구체적인 정보는 실수하기 쉽다.외부 자료나 공식 문서를 통해 교차 검증한다.검증 과정이 없으면 잘못된 정..

    [LLM] 모델을 갈아끼울 수 있게 만드는 구조

    LLM(대규모 언어 모델) 은 고정된 것이 아니라 상황에 따라 갈아끼울 수 있는 부품이다.시스템이 유연하려면 입력 처리부터 출력 생성까지의 구조를 분리해서 설계해야 한다.1. 데이터 전처리 모듈def preprocess(text): text = text.lower() text = re.sub(r'[^a-zA-Z0-9\s]', '', text) return text.split()문자를 소문자로 바꾸고 불필요한 기호를 제거한다.단어를 리스트로 쪼개서 모델이 이해하기 쉬운 형태로 만든다.언어 모델의 토큰화 방식과 상관없이 텍스트만 정제하면 된다.전처리 로직은 모델 종류와 무관하게 동일하게 적용할 수 있다.2. 임베딩 및 저장 모듈def embed_and_store(text, model): ..

    [LLM] 응답 시간이 정해져 있을 때 - 5 초 안에 답해야 하는 챗봇 만들기

    5 초 안에 답해야 하는 챗봇을 만들려면 어떤 기술을 써야 할까.응답 속도가 제한된 환경에서는 모델의 출력 속도를 조절하거나 스트리밍 방식을 활용해야 한다.1. 일반 텍스트 생성response = client.chat.complete(request);전체 응답을 한 번에 받아야 할 때 이 방법을 쓴다.사용자가 내용을 다 읽은 후 다음 동작을 취할 수 있게 해준다.단, 5 초 안에 완료되지 않으면 사용자가 이탈할 위험이 크다.2. 스트리밍 응답client.chat.stream(request).forEach(System.out::println);문자 하나하나를 실시간으로 보내며 화면에 띄운다.전체 응답이 5 초 걸려도 첫 단어를 0.5 초 만에 보여준다.사용자가 기다리는 느낌을 줄여주는 가장 효과적인 방식이..

    [Java] List, Set, Map 차이

    Java Collections Framework 에는 List, Set, Queue, Deque 등의 Collection 계열과 별도의 Map 계열이 있으며, Map 은 Collection 의 하위 인터페이스가 아니다.순서가 중요하면 List 를 쓴다.1. ListList list = new ArrayList();list.add("A");list.add("B");System.out.println(list); // [A, B]순서를 완벽하게 유지하는 자료구조다.중복된 값을 저장할 수 있다.인덱스를 통해 원소에 접근할 수 있지만 성능은 구현체에 따라 다르다. ArrayList 의 인덱스 접근은 O(1)이지만 LinkedList 는 최악의 경우 O(n)이다.순서가 중요한 경우나 중복이 필요한 경우에 쓴다.Ar..

    [CS] 뮤텍스(Mutex)와 세마포어(Semaphore) 차이

    뮤텍스와 세마포어는 공유 자원을 보호하는 도구다.두 가지 모두 스레드 간 경쟁을 막아준다.하지만 내부 동작 방식과 용도가 다르다.1. 뮤텍스 기본 개념ReentrantLock lock = new ReentrantLock();lock.lock();try { // 임계 영역 작업 수행} finally { lock.unlock();}뮤텍스는 최대 하나의 스레드만 접근할 수 있게 막는다.한 번 잠그면 다른 스레드는 대기 상태로 들어간다.잠금 해제 시 대기 중인 스레드가 우선순위를 얻는 방식은 구현에 따라 달라질 수 있다.임계 영역을 보호할 때 주로 사용된다.단일 자원을 독점적으로 사용할 때 적합하다.2. 세마포어 기본 개념Semaphore sem = new Semaphore(2);sem.acquire..

    [Java] equals() 를 재정의하면 hashCode() 도 재정의해야 하는 이유

    객체는 기본값을 쓰면 주소로 비교된다.내용이 같아도 다른 개체로 인식된다.equals() 를 재정의하면 반드시 hashCode() 도 같이 고쳐야 한다.1. 기본 동작 이해하기class Person { String name;}Person a = new Person();a.equals(b); // 주소 비교로 falseObject의 기본 equals()는 ==와 마찬가지로 두 참조가 동일한 객체를 가리키는지 비교한다.내용이 같아도 주소가 다르면 false 가 된다.equals()를 재정의하지 않으면 기본 equals()는 객체의 동일성을 비교하지만, 필드를 직접 비교하는 등의 별도 코드로 내용 비교를 할 수 있다.2. hashCode() 의 역할Map map = new HashMap();Person ..

    [JPA] 즉시 로딩 (EAGER) 과 지연 로딩 (LAZY) 차이

    엔티티의 관계 필드를 조회할 때 언제 데이터를 가져올지 정하는 정책이다.즉시 로딩은 관련 데이터를 바로 함께 가져오는 방식이다.지연 로딩은 실제 필요할 때까지 관련 데이터를 나중에 가져오는 방식이다.1. 즉시 로딩 (EAGER)@ManyToOne(fetch = FetchType.EAGER) private Department dept;엔티티를 조회하는 순간 관계된 데이터를 같이 가져온다.EAGER는 관계 데이터의 로딩 시점을 정하는 정책이며, JOIN이나 단일 쿼리 실행을 보장하지 않는다. 구현체와 조회 방식에 따라 JOIN 대신 추가 SELECT로 관계 데이터를 가져올 수 있다.관계 필드를 바로 쓸 때 편리하지만 불필요한 데이터가 포함될 수 있다.대형 테이블이 많을 경우 성능 저하와 메모리 사용량 증가를..

    [Spring] @RequestParam 과 @PathVariable 차이

    @RequestParam 은 URL 의 쿼리 스트링에 값을 담는다.예를 들어 ?name=홍길동 처럼 파라미터가 붙는 방식이다.반면 @PathVariable 는 URL 경로 자체에 변수를 넣는다./users/{id} 에서 {id} 위치에 값을 채우는 방식이다.쿼리 스트링은 여러 개를 동시에 받을 수 있다.경로 변수는 URL 구조에 딱 맞는 값만 들어간다.1. @RequestParam@GetMapping("/search")public String search(@RequestParam String query) { return "검색 결과: " + query;}이 코드는 GET 요청 시 ?query=스프링 을 받는다.쿼리 스트링은 여러 파라미터를 나열할 수 있다.예를 들어 ?query=스프링&sort=as..

    [CS] TCP 와 UDP 차이

    TCP 와 UDP 는 인터넷 통신의 두 가지 핵심 프로토콜이다.두 프로토콜은 목적지가 같지만 동작 방식과 사용처가 완전히 다르다.1. 연결 유무Socket tcp = new Socket(); // 연결 필요DatagramSocket udp = new DatagramSocket(); // 연결 불필요TCP 는 통신 전에 반드시 연결을 맺고 끊는다.연결이 없으면 데이터 전송 자체가 불가능하다.UDP 는 연결 없이 바로 데이터를 날려버린다.빠른 응답이 필요할 때 UDP 가 유리한 이유다.안정성이 최우선이라면 TCP 를 선택해야 한다.2. 데이터 신뢰성byte[] tcpData = "파일 전체".getBytes(); // 순서 보장byte[] udpData = new byte[1500]; // 순서 무관TCP ..

    [Java] 추상 클래스와 인터페이스 차이

    추상 클래스는 어떤 기능을 구현할지 정의하는 템플릿이다.인터페이스는 외부에서 사용할 수 있는 기능의 약속을 담는다.1. 구조적 차이public abstract class Animal {}추상 클래스는 extends 키워드로 하나만 상속받을 수 있다.인터페이스는 implements 키워드를 통해 여러 개 구현할 수 있다.클래스의 경우 변수나 생성자를 직접 정의해서 사용할 수 있다.2. 메서드 구현 방식abstract void eat(); // 추상메서드만 가능void sleep() {} // 일반메서드 가능추상 클래스는 추상메서드와 일반 메서드를 모두 정의할 수 있다.인터페이스는 자바 8 이전에는 추상메서드만 존재했다.자바 8 이후 default 와 static 메서드가 추가되어 변경되었다.3. ..