
data.txt 파일을 작성하여 Chatbot 폴더 하위에 저장했다.

교재와 같은 구조로 작성하였으며, 하단 정보는 실제 지인 이름을 사용한 예시여서 가리고 올린다.
# text_to_csv.pyimport pandas as pd
import re
def remove_new_lines(text):
text = re.sub(r'\n', ' ', text)
text = re.sub(r' +', ' ', text)
return text
def text_to_df(data_file):
texts = []
with open(data_file, 'r', encoding = 'utf-8') as file:
text = file.read()
sections = text.split('\n\n')
for section in sections:
lines = section.split('\n')
frame = lines[0]
content = ''.join(lines[1:])
texts.append([frame, content])
df = pd.DataFrame(texts, columns = ['fname', 'text'])
df['text'] = df['text'].apply(remove_new_lines)
return df
df = text_to_df('data.txt')
df.to_csv('scraped.csv', index = False, encoding = 'utf-8')
pandas 라이브러리
CSV, 데이터베이스의 테이블 등 표 형식의 데이터를 직관적으로 집계하고 조작할 수 있도록 하는 라이브러리이다.
remove_new_lines 함수
문자열의 개행과 연속된 공백을 삭제하는 함수이다.
text_to_df 함수
텍스트 파일을 처리하여 DataFrame을 반환하는 함수이다.
texts: 처리된 텍스트가 저장되는 빈 리스트
with open(data_file, 'r', encoding = 'utf-8') as file: 지정된 파일 data_file을 읽어들여 변수 file에 저장하고, 파일 내용을 문자열로 불러와(text) 개행으로 문자열을 두 줄로 나누어 sections에 저장한다. for문 안에서는 각 섹션에 대해서 섹션을 개행으로 나누고 첫 행을 frame, 나머지 행을 content에 저장한다. 최종적으로 frame과 content를 함께 texts에 리스트로 추가하고, 해당 리스트로 DataFrame을 생성한 뒤(df) 'text' 열(content)의 개행을 제거하여 반환한다.

파일을 실행하면 scraped.csv 파일이 정상적으로 생성된 걸 확인할 수 있다.
scraped.csv 파일을 임베딩하여 최종 벡터 데이터를 생성하는 단계이다.
# text_embedding.pyimport pandas as pd
import tiktoken
from openai import OpenAI
from typing import List
def split_into_many(text, max_tokens = 500):
sentences = text.split('.')
n_tokens = [len(tokenizer.encode(' ' + sentences)) for sentence in sentences]
chunks = []
tokens_so_far = 0
chunk = []
for sentence, token in zip(sentences, n_tokens):
if tokens_so_far + token > max_tokens:
chunks.append('. '.join(chunk) + '.')
chunk = []
tokens_so_far = 0
if token > max_tokens:
continue
chunk.append(sentence)
tokens_so_far += token + 1
if chunk:
chunks.append('. '.join(chunk) + '.')
return chunks
def get_embedding(text, model):
text = text.replace('\n', ' ')
return client.embeddings.create(input = [text], model = model).data[0].embedding
client = OpenAI()
embedding_model = 'text-embedding-3-small'
embedding_encoding = 'cl100k_base'
max_tokens = 1500
df = pd.read_csv('scraped.csv')
# 기존의 'fname', 'text' 열을 'title', 'text'로 읽어들임
df.columns = ['title', 'text']
tokenizer = tiktoken.get_encoding(embedding_encoding)
# 'text'의 토큰 수를 'n_tokens'라는 새로운 열로 저장
df['n_tokens'] = df.text.apply(lambda x: len(tokenizer.encode(x)))
# 축약된 텍스트가 저장될 리스트
shortened = []
for row in df.iterrows():
if row[1]['text'] is None:
continue
# 토큰 수가 최대 토큰 수보다 큰 경우, 텍스트를 shortened 리스트에 추가if row[1]['n_tokens'] > max_tokens:
shortened += split_into_many(row[1]['text'])
else:
shortened.append(row[1]['text'])
# shortened를 기반으로 새로운 DataFrame 생성하고, 열 이름으로 'text' 지정
df = pd.DataFrame(shortened, columns = ['text'])
# 각 'text'의 토큰 수 계산하여 'n_tokens' 열로 저장
df['n_tokens'] = df.text.apply(lambda x: len(tokenizer.encode(x)))
df['embeddings'] = df.text.apply(lambda x: get_embedding(x, model = embedding_model))
df.to_csv('embedding.csv')
tiktoken 라이브러리
OpenAI가 제공하는 토큰 수 계산할 수 있는 라이브러리이다.
split_into_many 함수
텍스트를 최대 토큰 수로 나눈다. 주어진 텍스트(text)를 문장 부호로 분할하여 각각의 토큰 수를 계산하는데, 최대 토큰 수를 넘지 않게 각 문장을 chunk로 분할하는 함수이다.
get_embedding 함수
임베딩을 수행한 결과를 새로운 'embeddings' 열로 저장하고 이 'embeddings' 열을 포함한 새로운 DataFrame을 'embeddings.csv' 파일로 저장하는 함수이다.
함수 외 코드에 관한 설명이 필요한 부분은 주석으로 작성하였다.

embedding.csv 파일까지 생성 완료!
다음 글: 내가 만든 데이터로 챗봇 작동