본문 바로가기
기술 단어장/AI

[Cohere] Cohere 기반 블로그 임베딩 & RAG 챗봇 구축 로직

by MFDO 2025. 10. 18.

이번에는 한창 만들고 있는

포트폴리오 사이트 세부 구현을 진행해볼 예정이다!

 

 

최종 목표

일단 배경으로 나는 내 대회 이력, 경력, 프로젝트, 블로그 콘텐츠들을

임베딩 형태로 Vector DB에 저장하고

RAG 기반 Chatbot을 통하여

내 정보를 제공할 수 있는 포트폴리오 사이트를 만드는 것이 목표이다.

 

 

 

VectorDB

Vector DB는 ChromaDB나 FAISS도 고려해보았지만,

단일 노드 기반의 확장성이 아쉬웠고, Pinecone는 무료 플랜의 제한이 있기에

Opensource 기반의 Millvus를 선택하게 되었다!

 

 

Embedding & Chatbot

무료 플랜에서 벡터 임베딩을 제공하면서도 1분에 10개의 request를 가능케 해주는

Cohere을 선택해 임베딩을 진행하고 있다!

 

 


 

현재 목표 및 요청 구조

 

 

 

 

1) 게시글 가져오기


나는 블로그 글의 링크가 숫자로 차례대로 진행되게 된다.

이를 활용해 접속할 링크는 숫자를 증가하면서 차례로 접근해 글을 가져올 수 있다.

글을 긁어오기 위해 Beautifulsoup를 가볍게 사용하였다.

 

 

 

또한 가져올 제목, 작성일, 내용은 Beautifulsoup에서 해당 요소의 selector를 이용해 가져오게 하였다.

 

 

 

# 마지막 글 번호가 대강 140후반이었음
for i in range(1, 150):
    record = Record()
    # 블로그 번호를 차례로 돌면서
    url = f'https://mfdo.tistory.com/{i}'
    response = requests.get(url)
    # 실제로 있는 글이라면
    if response.status_code == 200:
        soup = BeautifulSoup(response.text, 'html.parser')
		
        # Selector를 이용해 제목, 작성일, 내용을 긁어와
        title = soup.select_one('#content > div > div.post-cover > div > h1')
        date = soup.select_one('#content > div > div.post-cover > div > span.meta > span.date')
        content = soup.select_one('#content > div > div.entry-content')
		
        # 요청 레코드 형식에 저장
        record.title = title.get_text(strip=True) if title else ""
        record.startDate = date.get_text(strip=True) if date else ""
        record.description = content.get_text(strip=True) if content else ""

 

 

 


 

 

2) 게시글 벡터 임베딩

 

Cohere의 embed-v4.0 모델을 사용하여 임베딩을 해주었다.

# Cohere 연결 정보 및 임베딩할 텍스트를 받아 결과값 반환
def embed_description(co, text: str):
    if not text:
        raise ValueError("The description field cannot be empty.")

    res = co.embed(
        model=EMBED_MODEL,
        inputs=[{"content": [{"type": "text", "text": text}]}],
        input_type="classification",
        output_dimension=VECTOR_DIM,
        embedding_types=["float"]
    )

    return res.embeddings.float[0]

 

 

 


 

3) 게시글 스킬 및 분류 태그 생성 

 

나는 실제 기술 이름이나 플랫폼으로 분류할 수 있는건 Skill로

그 분야를 표현할 수 있는건 Tag로 남기고 싶었다.

 

 

이를 위해 Beautifulsoup가 받아온 게시글 내용+제목을

나의 프롬프트와 합하여 Cohere command-a-03-2025 모델에 전달하였다.

 

아래는 프롬프트다

사실 나에게 최적화해서 맞춰져있기 때문에 참고용으로 보면 좋다!

더보기

 

# 목적
블로그 글의 내용을 분석하여 다음 두 가지 항목을 자동 생성

## 생성 규칙
- 모두 영어로 작성
- 반드시 title과 content 둘 다 고려하되, title에 프로그래밍 언어나 알고리즘명이 포함되어 있으면 그 정보를 우선 반영
- title에 "요약지"라는 키워드가 있다면 title 내용만을 반영해 skills와 tags를 달 것
- [백준], [프로그래머스] 등 "알고리즘 문제 풀이" 관련 글은 무조건 ["Java", "Python", "C++"] 중 하나만 skills에 포함하고 tags는 ["Algorithm"]만 포함
- skills는 최소 0개, 최대 3개까지만 생성 (내용이 불분명하면 0개)
- tags는 최소 0개, 최대 3개까지만 생성
- skills에는 아래 예제의 기술만 사용하며, 새로 생성하지 않음
1. skills
   - 블로그의 개발 관련 기술 내용을 기반으로 생성
   - 기술, 도구, 프레임워크, 언어, 인프라 개념 등을 포함
   - ["AWS", "GCP", "Azure", "Kubernetes", "Docker", "Terraform", "Ansible", "Helm",
    "Prometheus", "Grafana",
    "Spring Boot", "Node.js", "FastAPI", "Flask",
    "Nginx", "Tomcat", "Redis", "Kafka", "Jenkins", "GitHub Action",
    "PyTorch", "TensorFlow", "Scikit-learn", "OpenCV",
    "React", "Next.js", "Vue.js", "Svelte", "TypeScript", "JavaScript", "HTML/CSS",
    "Android", "iOS", "React Native",
    "Python", "Java", "C++", "C#", "Go", "Rust", "Bash", "PowerShell",
    "Linux", "Ubuntu", "Debian", "CentOS", "macOS", "CentOS",
    "SQL", "PostgreSQL", "MySQL", "MariaDB", "MongoDB", "Git"]
2. tags
   - 로고형 기술이 아닌, 개념/역할/프로세스 중심 태그
   - ["DevOps", "Infrastructure", "Algorithm," "Automation", "IaC", "Backend", "Frontend", "Web", "Mobile",
 "API", "System Architecture", "Microservices",
 "Machine Learning", "Deep Learning", "AI", "Data Engineering", "Data Science",
 "Analytics", "MLOps", "Security", "Compliance",
 "Scripting", "Monitoring", "Testing", "Agile", "CI/CD", "Version",
 "Architecture", "Design Patterns", "Scalability", "Performance",
 "Reliability", "Cloud", "Networking", "Serverless", "Visualization",
 "UI/UX", "Collaboration", "Blockchain"]

## 출력 형식
결과는 오직 JSON 데이터만 출력

예시:
{
  "skills": ["Docker", "Terraform", "AWS"],
  "tags": ["Architecture", "Design Patterns", "Scalability"]
}

이후 부터는 해당 게시글 내용이다.

 

 

사실 질문이 길어지지 않기를 바랐는데 너무 무관한 태그들이 많거나

너무 태그 감이 잡히지 않은 내용들이 들어와있어 어찌저찌 저렇게 길어지게 되었다.

 

 

계속 결과를 보며 여러 방면으로 수정할 점도 떠오르고

변경하고 싶은 점도 많지만 이건 작은 기능 중 하나이기에

다음에 추가적으로 보수를 해보고자 한다.

 

 

데이터가 삽입된 모습

댓글