목차

  • 스트림릿 디자인 마무리
  • 다이어 그램 작성
  • README 문서 검토 및 수정

스트림릿 디자인 마무리

  1. 배경색 수정
    • config.toml 파일의 구조 파악
    • base에는 dark와 light만 사용가능 다른 색상을 사용하려면 HTML 스타일 적용해야합니다.
    • primaryColor에는 셀렉트 박스, 버튼 등의 색을 정의 해야합니다. 크기 및 UI개선을 위해서는 HTML 스타일 적용해야합니다.
    • backgroundColor: 서브배경 색상결정
    • secondaryBackgroundColor: 사이드 바 색상을 지정할 수 있습니다.
[theme]
base = "dark"  # 또는 "light"
primaryColor = "#37B7C3"
backgroundColor = "#1E1E1E"  # 서브 배경 색상
secondaryBackgroundColor = "#2A2A2A"  # 보조 배경 색상 (사이드바 등)
textColor = "#FFFFFF"  # 텍스트 색상
font = "sans serif"

2. 시간 체크 UI 구현

# 시간 및 날짜 출력 (매번 렌더링 시 갱신)
current_date_space = st.sidebar.empty()  # 빈 공간 생성
current_time_space = st.sidebar.empty()  # 빈 공간 생성

# 현재 날짜와 시간 출력
current_day = datetime.now().strftime('%Y-%m-%d')  # 현재 날짜 포맷팅
current_time = datetime.now().strftime('%H:%M:%S')  # 현재 시간 포맷팅

current_date_space.markdown(
    f'<p style="color:white; font-weight:bold;">현재 날짜 - {current_day}</p>',
    unsafe_allow_html=True,
)
current_time_space.markdown(
    f'<p style="color:white; font-weight:bold;">현재 시간 - {current_time}</p>',
    unsafe_allow_html=True,
)

다이어 그램 작성

다이아그램 웹사이트를 이용해서 스트리릿으로 구현한 페이지 구조를 보여줄 수 있게 만들었고 이를 합쳐 README에 올렸습니다.

 


README 문서 검토 및 수정

README 문서는 프로젝트의 기능 및 설계를 보여주는 것이라 생각했습니다.
README작성을 맡으신 팀원분이 대체적으로 작성하고 다른 팀원들이 따로 작성을 해보거나 첨언을 하는 형식으로 진행을 했고 저는 개선사항에 첨언을 넣었습니다.
최종적으로 우리 프로젝트를 잘 보여주는 문서를 작성했다고 생각하며 마무리했습니다.
마지막으로 노션으로 작성한 README를 README.md 파일로 옮기는 작업을 했습니다.
gpt를 사용해서 표 데이터를 마크다운으로 사용하는 방법을 익혔습니다.
개행을 넣는 방법과 표 데이터를 쓰는 방법 등 많은 정보를 얻을 수 있었습니다.

 


회고

처음 도전하는 팀 프로젝트인 만큼 많은 것을 배워 내것으로 만드는게 목표였습니다.


프로젝트를 마무리하며 목표를 생각했을 때 정말 많은 것을 배웠고 아직은 완전하지 않지만 성공적이였다고 생각합니다.

 

하지만 삐걱되는 부분도 많았습니다. 다들 처음하는 만큼 더욱 열심히하고 놓친 부분이 있어서 그랬다고 생각합니다.

 

- 프로그램을 진행하면서 아쉬웠던 부분은

   1. 기획단계와 구상단계에서 웹 사이트를 기준으로 기획안을 만들어야합니다.

   2. 코드 컨벤션을 진행해서 변수명이 통일 되어야합니다.

   3. 사용 환경을 일치시켜야합니다.

   4. 프론트엔드(Streamlit)을 구현하는 것이 처음이였기 때문에 구현 하고 싶었던 기능을 구현하지 못했습니다. (이후에도 이 프로젝트를 수정하려고 합니다.)

 

- 프로그램을 진해아며 좋았던 점

  1. RAG, langchain, OpenAI, FAISS, Retrieval 등의기능과 흐름을 자세히 알게되는 시간이였습니다.

  2. Streamlit UI의 구조 등 기본적인 것들과 구축 단계에 대해 자세히 알게 되었고 이후에는 구상하는 단계에서 어떤 기능을 추가해야할지 생각하는데 도움이 될것같으며 아직 파이썬 문법에 많이 약해 각 기능을 함수로 지정하여 부르는 부분은 조금 더 노력해야할 것으로 생각합니다.

 

개선사항으로 넘어간 기능들이 아쉽긴 하지만 모두 서로 존중해주며 서로의 의견을 귀담아 들어 프로젝트를 잘 마무리하는 것 같습니다.


프로젝트를 진행하며 재밋고 힘들었지만 뿌듯한 마음이 가장 큼니다. 김준기님 이다원님 전상우님 정말 감사합니다.

목차

  1. 스트림릿 과제를 하며 만난 트러블 슈팅

트러블 슈팅

  • st.set_page_config()의 위치: 이 함수는 항상 가장 위 import구문들 아래에 배치 시켜야지 작동이 됩니다.
    • Streamlit의 레이아웃 및 초기 설정이 앱이 처음 로드될 때 결정되기 때문입니다.
  • 카테고리 설정 selectbox에 "설정하지 않음" 추가: 주제를 선택하지 않아도 자동으로 선택 되어 모델이 작동해 사용에 불편감을 없애기 위해서 사용하였습니다.
    • NONE파일을 만들어서 경로 추가 했습니다.
  • 로그인 화면을 어떻게 구상할지, 어디에 위치 시킬지: 로그인 화면으로 넘어가는 버튼을 만들고 싶었지만 구현하지 못해 처음 웹사이트에 접속했을 때 작동 되게 만들었습니다.
  • 로그인 정보를 다른 페이지에 가서도 정보확인 하기: 다른 페이지에서는 설정이 되지 않아 정보가 없어도 작동 되기 때문에 보안을 높이기 위해서 설정하였습니다.
    • json파일에 로드 된 정보를 읽어오고 이전 페이지의 session_state를 읽어와 정보를 확인하게 만들었습니다.
# 사용자 데이터 경로
users_file_path = pathlib.Path("users.json")

# 사용자 데이터 로드 함수
def load_users():
    if users_file_path.exists():
        with open(users_file_path, 'r', encoding='utf-8') as f:
            return json.load(f)
    return {}

# 세션 상태 초기화
if "user_id" not in st.session_state:
    st.session_state["user_id"] = None  # 초기값 설정

# 로그인된 사용자 확인
if not st.session_state["user_id"]:
    st.error("로그인되지 않았습니다. 먼저 로그인해주세요.")
    st.stop()

users = load_users()
user_id = st.session_state["user_id"]

if user_id not in users:
    st.error("사용자 정보를 확인할 수 없습니다. 다시 로그인해주세요.")
    st.stop()

st.success(f"환영합니다, {user_id}님!")
  • 경고 문구를 줄였습니다.
    • 화면에 나오는 인터페이스가 너무 많아 줄였습니다. 줄이는 방법으로는 st.error,st.success, st.waring 등의 문구 중 궅이 필요하지 않은 문구들을 st.write()로 빈 문자열을 주게하여 수정했습니다.
  • 질문 선택만 해도 질문에 대한 답변을 해서 사용자가 입력할 시에 답변을하게 수정하였습니다.
    • 프롬프트 간결화 및 명령 추가('사용자가 답변을 하기전에 대답을 먼저 하지마') => 실패
    • vectorstore 확인 후 초기화 => 질문만 출력 되게 했지만 프롬프트대로 답변을 하지 않음
    • if selected_question:, if user_input: 조건 분리 => 해결 (조건이 겹치는 부분이있어 분리해서 정의했습니다.)
  • 스트림 형식으로 출력해 사용자의 이용에 불편함을 줄일려고했습니다.
    • st.write_stream을 사용했지만 적용 되지않았습니다.
  • 경고 문구 중 너무 딱딱한 경고 문구가있어 수정했습니다.
    • 변경 전: FAISS를 찾을 수 없습니다. 다시 시도하세요.
    • 변경 후: FAISS 인덱스를 찾고 있습니다. 잠시만 기다려 주세요.
  • 색 배치: 컬러 헌터 싸이트를 이용해 팀원들과 회의를 했고 사용할 컬러들의 조합을 맞추어 프론트 팀원과 협의하여 색을 구성했습니다.
    • 텍스트 기반으로 학습을 하는 LLM이기 때문에 차분한 분위기로 설정 하였습니다.
배경 #071952
사이드 바, 셀렉트 박스 #088395
버튼 #37B7C3
텍스트 EBF4F6
  • 배너의 크기를 조절하기 위해서 css스타일을 추가했지만 실패
    • import base64를 통해 toml 파일과 css, html 스타일을 불러와서 적용하였습니다.
    • base64는 이진 데이터를 텍스트 형식으로 변환하는 인코딩 방식으로 안전하게 데이터를 불러 올 수 있습니다.

목차

오늘의 TIL 순서는

  1. 시작전 마음가짐
  2. Streamlit 구현
  3. 수준별 학습반

코드는 GITHUB 링크를 확인해주세요

 

TIL/basic at main · Onesword-Jang/TIL

오늘 배운 것은?! Contribute to Onesword-Jang/TIL development by creating an account on GitHub.

github.com

 

 

RAG_project/app.py at 1-장한검 · maricecil/RAG_project

Contribute to maricecil/RAG_project development by creating an account on GitHub.

github.com

 


시작전 마음가짐

어제 TIL을 보니 너무 TIL에 소홀해진 느낌이 들었습니다.

 

진행되는 과정 중 새롭게 알게 된 내용이나 트러블이 나온다면 제대로 기록하는 것이 목표입니다.

 

또한 스트림릿을 받은 코드로 구현하는 것이 최종 목표입니다.

 

학습을 시작하겟습니다.


Streamlit 구현

팀원의 코드를 받아서 카테고리를 정하고 질문지를 가져와 사용자가 선택해서 채팅형태로 대답을 하고 튜터링을 받는 웹사이트를 구현하는 것을 목표로 진행하고있습니다.

 

오늘 시작은 준기님의 코드를 파악하고 사용자 지정함수를 만드는 과정, 지정 함수를 어떤 기능에 어떻게 집어넣을지 파악하였습니다.

# PDF 처리 함수
def process_pdf(file_path, api_key):
    """PDF 파일을 처리하여 텍스트 청크를 반환."""
    loader = PyPDFLoader(file_path)
    documents = loader.load()
    text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
    split_texts = text_splitter.split_documents(documents)
    return split_texts

# 질문 파일 로드 함수
def load_questions(topic):
    """카테고리별 질문 파일을 로드."""
    file_name = topic_file_mapping.get(topic)
    if not file_name:
        return []
    questions_file = os.path.join(questions_folder, file_name)
    if not os.path.exists(questions_file):
        return []
    with open(questions_file, "r", encoding="utf-8") as file:
        questions = file.readlines()
    return [q.strip() for q in questions if q.strip()]  # 공백 제거

# FAISS 저장 및 로드 함수
def save_faiss_index(vectorstore, topic):
    """FAISS 인덱스를 주제별로 저장."""
    sanitized_topic = topic_file_mapping.get(topic, topic).replace("_module.txt", "")
    index_path = os.path.join(faiss_index_folder, f"{sanitized_topic}_index")
    os.makedirs(index_path, exist_ok=True)
    vectorstore.save_local(index_path)

def load_faiss_index(topic, api_key):
    """주제별로 저장된 FAISS 인덱스를 로드."""
    sanitized_topic = topic_file_mapping.get(topic, topic).replace("_module.txt", "")
    index_path = os.path.join(faiss_index_folder, f"{sanitized_topic}_index")
    if os.path.exists(index_path):
        embeddings = OpenAIEmbeddings(openai_api_key=api_key)
        return FAISS.load_local(index_path, embeddings, allow_dangerous_deserialization=True)
    return None

4가지 사용자 지정 함수를 만들었습니다.

 

이를 활용할 수 있게 파일 경로와 카테고리 이름을 file_path로 매핑해서 저장 하였고 질문지 또한 마찬가지로 진행하였습니다.

 

현재 기초적으로 작동하는 부분은 구현을 마쳤습니다.

 

그리고 지금까지 해온게 킴원분의 코드에서 많이 벗어난다는 느낌이 들어 팀원분의 의견을 생각하며 다른게 무엇인지 고민해보았습니다.

 

  1. faiss에 문서들이 저장 된 형태라서 1번 문서를 불러오면 다음부터는 필요가 없음.
  2. 다국어 지원이 가능 함
  3. 대화 내용을 기억하고 관리 할 수 있음

지금 내가 구현 하지 못한 부분이기도 하면서 많이 다르다고 느껴진게 1번입니다.

 

그래서 배포를 할 때는 최초의 한번 데이터를 불러오고 저장하는 방법이 없기 때문에 해결 방법을 고민해 보았습니다.

  • solution
  • 데이터베이스 활용
  • 클라우드 스토리지 활용
  • REST API로 데이터 제공
  • 벡터 데이터 저장 및 검색

이렇게 검색의 되었고 가장 단순한 방법이 벡터 데이터 저장 및 검색이라고 생각을 했고 이는 문서에서 text테이터를 추출해 그 데이터를 리스트로 저장하여 같이 배포하는 형태였습니다.

 

우선 이렇게 내 마음대로 해도 될지가 고민이였지만 지금 고민할거리가 아니라는 생각에 이제는 프롬프트 적용하는 방법을 구현해야 할듯 합니다.


Python 문법 수업

오늘은 파이썬 기초 문법을 공부하는 시간을 가졌습니다.

 

튜터님께서 만들어주신 문제를 풀어보다가 여러가지 인자받기에서 어려움을 느꼇습니다.


회고

시간이 늦어 회고는 조금 짧습니다.

 

어떤걸 구현할지 어떻게 구현할지 감이 잡히지 않아 일단 필수 구현부분을 GPT의 도움을 받아 작성하고있었습니다.

 

제가 맏은 세션의 챗봇의 기동은 성공적이였지만 아직 질문 선택시 대답하기 전에 답을 말해버리는 오류가 생겼습니다.

 

분명 잘되었는데 이를 수정할 방법을 생각하다가 같은 팀원분이 이대로가면 완성을 못할 것 같다고 한가지 세션을 같이 고민하자는 의견을 듣고 같이 화면 공유를 하며 오류를 해결해보았고 이는 괸장히 성공적이였습니다.

 

그래서 우선 같이 한 세션을 구현하기로 했습니다.

 

감사합니다.

목차

오늘의 TIL 순서는

  1. 시작전 마음가짐
  2. JIRA, GITHUB 특강
  3. Streamlit 구현

시작전 마음가짐

오늘은 진짜 전체적으로 streamlit을 팀과제에 사용할 수 있게 만들 생각입니다.

 

중간에 특강이 하나 있는데 이 특강도 확실하게 습득하겟습니다.

 

그럼 학습을 시작하겟습니다


JIRA, GITHUB 특강

JIRA특강을 듣고 현재 팀 과제에는 적용하면 좋겟지만 당장 적용하기에는 진행 되어있는 부분이 많아 진행하지 않을것입니다.

 

왜냐하면 팀 내부적으로 github의 프로젝트를 사용하는 방법을 공유하고 같이 학습한 사태이기 때문입니다.

 

하지만 다음 프로젝트부터는 적극적으로 도입하면 좋을거같다 생각합니다.

 

그리고 github랑 여결하는 부분이 애매하게 이해가 되어서 다음에 한번더 복습을 진행해야할듯 합니다

.


Streamlit 구현

본격적으로 팀과제에 도입을 하고싶어서 프론트엔드를 맡은 팀원과 상의해서 진행 방향을 정했습니다.

 

특강도 듣고 따로 학습을 진행했지만 모델에 연결하는 부분이 미흡하다는 생각으로 각자 학습을 통해 이해한 부분을 공유하고 다음 진해을 결정하는 방식으로 설계를 하였습니다.

 

오늘 학습을 마무리하며 공유를 했는데 어떤 부분에 이 코들를 넣으면 좋을지 즉, 아직 모델을 연결하는 부분까지는 구현 못해서 각자 어떤 세션을 구현할지 이야기를 나누었구요 그런데 제가 맡은 부분이 약간 도전과제 부분이라 확실하게 팀원들의 의견을 들어도 정해지짖 않았습니다.

 

왜냐하면 필수과제를 구현하는건 팀원분이고 저는 도전 과제를 구현하기로 했기 때문입니다.

 

새롭게 학습한 부분이 많지만 과제를 ㅇ어떻게 진행할지 감이 잡히질 않습니다.

 

조금더 깊게 그리고 기한에 맞게 생각하고 행공해야하지만 욕심을 버리기 어렵습니다.

 

프론트엔드 팀원끼리 정한 부분과 팀 전체적으로 정한 부분이 어긋났기 때문입니다.

 

다들 프로젝트를 진행하는게 처음이라 기획을 맡은 사람이있는게 아니라 진행상황을 보며 토론을 통해 진행을 계속 수저하고있기 때문이라 생각합니다.

 

기획이라는 부분이 중요하는걸 깨달았습니다.

 

감사합니다.

 

목차

오늘의 TIL 순서는

  1. 시작전 마음가짐
  2. langchain 특강 2
  3. Streamlit 예습
  4. Stramlit 특강 4일차
  5. langchain 특강 3,4
  6. 회고

시작전 마음가짐

오늘은 전처리작업도 드디어 끝났겟다.

 

스트림릿을 모델에 연결하는 작업을 진행할 생각입니다.

 

빠르게 끝난다면 스트림릿을 이용해 최대한 꾸미는 작업도 해볼 생각입니다.

 

langchain특강 2를 어제 놓쳤는데 녹화본을 보며 학습을 시작하겟습니다.

(강의가 아직 올라오지 않아 streamlit예습을 먼저 하겟습니다.)


Stramlit 예습

아래 출처에서 RAG와 Streamlit을 연결한 챗봇을 만드는 방법에 대하여 학습하였습니다.

 

이번 학습으로 팀과제에 사용하면 좋을 부분이있어 참고하기 좋아보인다.

아래 docs를 활용해서 Streamlit의 ui구성하는 방법에 대하여 공부하였습니다.

 

끝까지 진행하려했지만 팀 회의에서 좋은 학습 방법이있어 다른 방법으로 학습하였습니다.

아래 출처를 활용해 코드와 홈페이지가 어떻게 구성 되는지 확인하며 요소 하나하나 공부하였고 이를 팀과제에 적용하게끔 바꾸어 주었습니다.

 

마지막에 깨달은 거지만 이 코드는 챗봇에 대한 소개를하는 화면이고 챗봇과 연결 되어있지는 않았습니다.

 

내일은 switch_page를 어떻게 사용하는지 학습할 예정입니다.


streamlit 특강 4일차

사용 파일

  • streamlit_d4.py

목표

  • 최적화 기법을 활용한 고급

Streamlit 데코레이터와 상태관리

  • 데이터 상태와 남아있는 데이터
    • 캐시(cache): 브라우저에 남아있는 데이터 (휘발성 데이터)
    • 브라우저에서 f12 입력 => Application => cache storage에서 데이터 확인 가능
  • 데코레이터(Decorator): def 함수가 실행 되기 직전에 바로 실행되는 함수

세션 상태 초기화 방법

  • 세션(Session): 인터넷 연결이 유지 돠는것 (나갓다 들어와도 유지 되는 것)
  • Streamlit 앱이 다시 로드될 때 상태를 유지하는 것

캐싱과 데이터 상태

HTML/CSS 기반 커스터마이징

  • CSS(Cascade Style Sheet/ 하강형 스타일 시트/ 웹페이지를 이쁘게 만들어 줌
  • javascpript와 연동

고급 레이아웃 설계

데이터 시각화와 심화


langchain 특강 3,4

이번 특강으로 langchain의 가장 어렵다고 생각한 부분과 추가기능 및 고급 기술을 구현하는 방법을 확인하였습니다.

 

재미있는 수업이였지만 실습을 하며 아~ 이런게 있구나 정도로 이해하고 넘어갓습니다.

 

아마 팀과제가 끝나고 나서 복습을 하면 좋을 것으로 생각합니다.


회고

현재 프로젝트의 흐름이 조금 빠그라졌다? 라고 생각합니다.

 

의견이 나오고 회의 때마다 좋다고 생각하는 쪽으로 의견수렴하는 형태로 진행하였는데 현재 가닥이 조금씩 잡히면서 이렇게할껄 이런 생각이 많이 든다고 생각합니다.

 

팀회의 때 솔직히 하기 어려운 이야기였지만 이후 진행과 기간에 맞추려면 지금까지 나온 의견에서 잘 판단해서 쳐낼건 쳐내야한다고 말을했는데 아무도 대답을 하지않아 조금 불만입니다.

 

그래도 의견을 어필하였다는데 의미를 둡니다.

 

이때까지 높은 완성도를 노리고 진행해왔기 때문에 말하기 어렵고 의견내기 어려운 주제여다고 생각합니다.

 

감사합니다.

+ Recent posts