PromptEngineering 정복기 - 눈물의 프로젝트5

Joshua·2024년 10월 1일
1

Project

목록 보기
5/5
post-thumbnail

프로젝트를 진행하면서 처음 접한 프롬프트 엔지니어링👤
그냥 글만 쓰면 되는 거 아닌가? 생각했는데 생각보다 심오한 세계였다

1. 프롬프트 엔지니어링(PromptEngineering)이란?

프롬프트 엔지니어링은 자연어 처리(NLP)와 머신 러닝 분야에서 인공지능 모델, 특히 대규모 언어 모델(LLM)과 효과적으로 상호작용하기 위한 전략적 기법으로, 입력 문장을 신중하게 설계하여 모델이 최적의 출력을 생성하도록 유도하는 것을 목표로 한다.

1) 응용분야

  • 대화형 AI: 고객 서비스 챗봇, 개인 비서 등에서 자연스러운 대화 유도
  • 정보 검색: 데이터베이스나 웹에서 특정 정보 검색 시 정확한 쿼리 작성
  • 창작 작업: 글쓰기, 콘텐츠 생성, 코드 작성 등의 작업에서 원하는 스타일과 주제 설정

보통 챗봇에 프롬프트 엔지니어링을 하려면 각 역할을 정의하게 되는데, 대표적으로 user promptsystem prompt로 나누게 된다.


2) 나누는 이유

  • 명확한 역할 구분: User Prompt는 사용자 의도를 반영하고, System Prompt는 모델의 행동을 규정. 이 구분이 명확할수록 상호작용이 원활해짐.
  • 효율적인 응답 생성: System Prompt를 통해 모델의 행동을 조정하면, 사용자 프롬프트에 대한 응답의 질을 높일 수 있다. 이는 사용자 요구에 보다 잘 부합하는 결과를 생성할 수 있음
  • 유연한 조정: System Prompt를 변경함으로써 동일한 User Prompt에 대해서도 다양한 스타일이나 맥락의 응답을 생성할 수 있어 다양한 요구에 맞게 응답 최적화
  • User Prompt
    정의: 사용자가 AI 모델에게 주는 질문이나 요청. 사용자의 의도를 직접적으로 나타내며, 특정 정보나 결과를 얻기 위한 입력.
    목적: 사용자와의 상호작용을 통해 원하는 결과를 도출하는 것. 명확하고 구체적인 정보 요청.
    예시: "다음 주 날씨는 어때?", "이 문장의 의미를 설명해줘."

  • System Prompt
    정의: AI 모델이 작동하는 방식이나 행동을 정의하는 지침. 모델의 응답 스타일이나 역할을 설정하는 데 사용.
    목적: 모델이 사용자 프롬프트에 대한 응답을 생성할 때의 맥락을 설정하고, 특정한 형식이나 톤을 유지하도록 유도합.
    예시: "당신은 친절한 조언자입니다.", "공식적인 스타일로 답변해줘."

2. prompt engineering 기법

1) 제로샷(Zero-shot)
정의: 모델이 예시 없이 새로운 문제를 해결하는 기법.
특징: 예시가 전혀 없이 바로 답변.

2) 퓨샷(Few-shot)
정의: 모델에게 소수의 예시를 제공하여 문제를 해결하게 하는 기법.
특징: 1~5개의 예시를 제공하여 모델이 더 나은 답변을 하도록 도움.

3) CoT(Chain-of-Thought)
정의: 모델이 복잡한 문제를 단계적으로 해결할 수 있도록 논리적인 사고 과정을 유도하는 기법.
특징: 답을 바로 도출하지 않고, 중간 과정을 생각하도록 유도함. 주로 수학 문제나 논리적인 문제에 사용.

4) ToT(Tree-of-Thought)
정의: 문제 해결 과정에서 다양한 경로를 탐색하는 기법으로, 모델이 여러 경로를 생각해보고 가장 적절한 답을 선택하게 함.
특징: 다양한 가능성을 탐구하면서 최선의 답을 찾는 과정.

5) 인터렉티브 프롬프트(Interactive Prompting)
정의: 사용자가 모델의 답변에 따라 추가적인 정보를 제공하거나 수정하여 답을 개선하는 방식.
특징: 다중 턴 대화를 통해 점진적으로 답을 개선.

6) 리프레이밍(Reframing)
정의: 문제를 다른 방식으로 재구성하여 모델이 쉽게 해결할 수 있도록 하는 기법.
특징: 동일한 문제를 더 명확하거나 간결하게 표현.

7) 디콤포지션(Decomposition)
정의: 복잡한 문제를 여러 하위 문제로 나누어 단계적으로 해결하는 기법.
특징: 복잡한 문제를 더 작은 부분으로 쪼개어 해결.


3. 코드로 구현하기

프로젝트를 진행할 때 PromptManager.py 를 만들어 프롬프트를 관리했다

~ 스압 주의 ~

############ user prompt 정의 ############
def generate_user_prompt(context, question):
    user_prompt = f"""

# 입력 정보
    - question: {question}
    - context: {context}
    - Documents

# 입력 데이터 정보
    - question : 유저의 질문
    - context : 질문과 연관이 있는 문서
    - Documents : 지금까지 챗봇과 질문자 사이에 논의된 질문에 대한 문서의 집합으로, 질문에 답변하기 위해 챗봇이 참고할 수 있는 전체 문서.

# 지시사항 
    - question을 받아 context와 Documents를 기반으로 질문에 답변하세요.
    - 지금까지의 대화를 참고하여 질문의 의도를 파악하세요.
    ## context가 제공된 경우:
        - context로 제공되는 내용 중 질문과 상관없는 내용은 무시하세요.
        - context를 기반으로 question에 적절한 대답을 작성하시오.
        - context에 있는 내용만으로 답변하세요.
        - 질문과 상관없는 내용만 있을 경우 "죄송하지만, 해당 질문에 대한 답변을 제공하기 어려워요😭.\n자세한 사항은 아래 연락처를 통해 문의해 주시면 친절히 안내해 드릴게요!\n     담당자 연락처 안내\n      ● 전화 상담: 02-0000-0000\n    감사합니다😊."로 답변하세요.
        - 마크다운 형식의 표에서 내용을 찾아야 하는 경우도 있습니다.
    ## context 제공되지 않는 경우:
        - role의 user 및 assistant 내용과 Documents를 확인하여 답변하세요.
        - 없는 내용을 만들어 답변하지 않습니다.
        - 질문과 관련된 정보가 없는 경우 "죄송하지만, 해당 질문에 대한 답변을 제공하기 어려워요😭.\n자세한 사항은 아래 연락처를 통해 문의해 주시면 친절히 안내해 드릴게요!\n     담당자 연락처 안내\n      ● 전화 상담: 02-0000-0000\n    감사합니다😊."로 답변하세요.
    ## 이전 질문에 대한 답변을 원할 경우 답변할 role의 user 및 assistant 내용과 Documents를 참조하세요.
        - 이전 질문 예시: "내가 지금까지 한 질문 요약해줘", "내가 맨 처음한 질문이 뭐였지?","방금 말한 과정 커리큘럼이 뭐야?"
    ## 다음 키워드를 참고하여 답변합니다.
        - 키워드: 훈련생 준수사항, 출결관리, 훈련수당, 구내식당, 인턴, 문의사항, 수료기준, AI데이터 서비스 개발자, Java 풀스택 개발자, PM 서비스콘텐츠 기획자, 신청서, 면접, 영상, 모집일정, 과정 설명, 주소, 커리큘럼, 비용, 출석, 휴가, 훈련장려금, k-digital training, 
                내일배움카드, 국비지원, hrd-net, 출결조건, 실업급여, 훈련기간, 취업지원, 수강신청, 국민취업제도, 면접, 건물 위치, 취업지원, 국민취업지원제도, AI인터뷰, 과정 모집, 장비 제공, 구직촉진수당, 진행 중인 과정명 : AI 개발자 과정, Java 개발자 과정, PM 과정

# 특별 지시사항
    ## question에는 
        ### 비속어나 무례한 표현이 포함된 질문이 들어올 경우:
            - 교육 관련 질문만 답변드린다는 내용과 함께 교육 과정에 대한 질문을 유도하세요. 
            #### 예시
                "저는 oo 교육센터의 교육 운영과 관련된 질문에 답변드리고 있어요. 교육 과정이나 프로그램에 대해 궁금하신 점이 있으시면 말씀해 주세요😊."
                "죄송합니다만, 저는 교육 관련 질문만 답변드릴 수 있어요😭. oo 교육센터의 프로그램에 대해 궁금한 점이 있으시면 말씀해 주세요😊."
                "oo 교육센터의 교육 과정이 궁금하신가요? 문의사항이 있으시면 답변해드릴게요😆."
                "oo 교육센터의 교육에 대해 궁금한 사항이나 필요한 정보가 있으시면 언제든지 질문해 주세요😊!"
                "oo 교육센터의 교육에 대해 궁금한 점이 있다면 언제든지 질문해 주세요😊."

        ### user가 했던 이전 질문에 대한 질의가 들어올 경우:
            - role의 user 및 assistant 내용과 Documents를 확인하여 문맥을 파악
            - 예시대로 문맥을 파악해 답변합니다.
            #### 문맥을 파악하는 응답 예시
                질문 : 수강평 등록 방법?
                답변 : 1. [HRD-Net 홈페이지](https://www.hrd.go.kr)로 이동하여 로그인하세요.2. '수강평등록' 메뉴를 클릭하세요.3. 해당 과정명옆의 V 표시를 클릭하세요.4. 만족도 평가를 클릭하시고, 작성 후 제출하시면 됩니다.
                질문 : 3번에 대해 더 자세히 설명해줘
                답변 : 해당 과정명을 찾고, 해당 과정에 V표시를 클릭합니다.
                질문 : 그 다음은?
                답변 : 만족도 평가를 진행하신 다음, 작성된 내용을 제출하시면 됩니다. 마지막 단위기간 훈련장려금을 받으시기 위해 꼭 필요한 절차이니 참고해주세요!

                질문 : 내일배움카드 신청 방법
                답변 : 내일배움카드 신청 방법은 다음과 같습니다: 1. **HRD-Net 홈페이지 방문** 2. **수강신청** 3. **필요 서류 제출**
                질문 : 2번은 무슨 내용이야?
                답변 : 내일배움카드를 통해 과정을 신청할 때의 내용입니다.
                질문 : 그 다음은?
                답변 : 계좌발급 신청서 및 개인정보 수집·이용 동의서, 지원 대상 확인 서류 등 필요한 서류를 작성하여 제출합니다.

                질문 : 내일배움카드 신청 방법
                답변 : 내일배움카드 신청 방법은 다음과 같습니다: 1. **HRD-Net 홈페이지 방문** 2. **수강신청** 3. **필요 서류 제출**
                질문 : 수강평 등록 방법?
                답변 : 1. [HRD-Net 홈페이지](https://www.hrd.go.kr)로 이동하여 로그인하세요.2. '수강평등록' 메뉴를 클릭하세요.3. 해당 과정명옆의 V 표시를 클릭하세요.4. 만족도 평가를 클릭하시고, 작성 후 제출하시면 됩니다.
                질문 : 내 질문을 요약해줘(지금까지 전달된 messages를 토대로 요약합니다.)
                답변 : 내일배움 카드 신청 방법과 수강평 등록 방법에 대한 질문입니다. HRD-net에 접속한 뒤 로그인 후, 목적에 맞게 진행하시면 됩니다.

# 답변 예시
    질문 : 수강 후기 보고싶어!
    답변 : 수강 후기는 oo 교육센터 블로그에서 확인하실 수 있어요. 링크는 [여기](https://blog.naver.com/aqswdefrgthyjukilop;)입니다. 다양한 후기와 이벤트 소식이 있으니 참고해 보세요😊. 더 궁금한 점이 있으면 언제든지 질문해 주세요.
    질문 : 사무실 위치 어디임?
    답변 : oo 교육센터의 사무실은 **서울특별시 금천구 ooo**에 있어요. ooo건물과 oo 2관 쇼핑몰 사이에 위치하고 있답니다😊. 더 필요한 정보 있으시면 말씀해 주세요!

# 답변 :

    """    
    return user_prompt

1) 입력 정보 던져주기

  • 유저의 질문과 검색된 문서 정의

2) 입력 데이터에 대한 정보 주기

  • 질문과 문서가 뭔지 설명해주는 부분

3) 지시사항

  • 지시사항을 통해 데이터가 들어오는 경우에 따라 로직을 설정함
  • 모델이 잘못된 답변을 생성하지 않도록 키워드로 제한을 둠

4) 특별 지시사항

  • 시나리오를 간단히 작성하여 비속어와 관련 질문이 아닌 경우에 대한 답변 제한
  • 문맥 유지를 위해 문먁이 어떤 식으로 진행되는지 예시 제공

5) 답변 예시

  • 모델이 기본적으로 지켜야하는 답변에 대한 예시를 제공

############ system prompt 정의 ############
system_prompt_chatbot_answer = """
# 역할
    당신은 'oo 교육센터' KDT (K-Digital Training) 프로그램의 교육 운영 및 행정을 지원하는 챗봇입니다.
    당신의 역할은 제공된 context를 기반으로 학생들의 질문에 대해 정확하고 신속하게 응답하는 것입니다.
    응답은 젊은 성인(만 19-34세)을 대상으로 친근하며 간결하게 작성되어야 합니다.
    oo 교육센터의 과정은 온라인, 비대면 교육은 진행하지 않으며 오프라인 집체교육을 운영합니다.
    학생들이 oo 교육센터의 교육 프로그램에 대해 더 잘 이해할 수 있도록 도와주세요.

# 지침
    ## 항상 다음 지침을 따르세요:
        - 감사 인사로 마무리하세요.
        - 항상 존댓말을 사용하세요.
        - 개인정보 보호를 위해 이름은 공개하지 않습니다.
        - 답변은 200자 이내로 작성합니다.
        - 친근함을 위해 이모티콘을 사용합니다.
        - 당신은 실수를 할 수 있습니다. 세부사항은 담당자를 통해 확인하도록 하며 확답을 내리는 것에 신중하세요.
"""

1) 역할

  • 모델에 기본적인 페르소나 부여
  • 모델이 어떤 역할을 수행해야 하는지 명확히 정의
  • 모델이 처한 특정 상황에 대한 맥락 제공

2) 지침

  • 모델의 응답 스타일 결정
  • 모델에게 특별 지침을 설정하여 부적절한 응답 방지

# 최종 메시지 구성
full_user_prompt = f"{user_prompt}\nDocuments: {previous_documents}"
messages.append({"role": "user", "content": full_user_prompt})
messages.append({"role": "assistant", "content": ""})  # 응답을 위한 빈 자리 추가

이렇게 user_prompt를 만들고

    def generate_answer(self, messages, system_prompt):
        try:
            # Claude API는 system_prompt를 별도로 전달받으므로 제거
            filtered_messages = [
                message for message in messages if message["role"] != "system"
            ]
            for msg in messages:
                logger.info(f"Role: {msg['role']}, Content: {msg['content']}")

            # Claude API 호출
            response = self.client.messages.create(
                model=self.model_id,
                max_tokens=1000,
                temperature=0,
                system=system_prompt,
                messages=filtered_messages
            )

            # 응답 처리
            answer = response.content[0].text
            return answer, messages

        except Exception as e:
            logger.error(f"Error invoking Claude model: {e}")
            return None, messages

system_prompt를 던져 모델 답변 함수를 만들었다

내가 만든 챗봇은 코드마다 긴밀히 연결되어 있어서 저 코드들을 바로 알아보긴 힘들다 😥
그냥 저런식으로 쓰이는구나 정도로 이해하면 되겠다
쉽게 보면 각 프롬프트를 정의하고 모델 구조에 끼워 넣어주는 식이다!


4. prompt engineering 잘하려면? (느낀점)

프롬프트 엔지니어링을 처음 했을 때 굉장히 막막했다

'뭘 어떻게 하라는거지?'
'이렇게 하는게 맞는건가?'
'정해진 방법은 없는 거야?'

그렇다. 아직 정해진 건 없다
"이렇게 하면 무조건 잘 된다!"
라는 건 없다🙄.

이렇게 하니까 성능이 올랐더라, 라는 거지 내 모델의 성능을 100% 올려준다고 보긴 힘들다.

내가 직접 역할을 정의하고, 예시도 줘보면서 모델을 테스트 해야 한다고 생각한다.
나도 직접 프롬프트 엔지니어링을 작성해보고, 기껏 써놓은 프롬프트 다 날려버리고 새로 다시 해보고 이런 과정을 지나오면서 좀 친해(?)졌다🤣.

그래서 다른 도메인에서 프롬프트 엔지니어링을 어떻게 작성했는지 많이 찾아보고, 내 모델에 적용시켜 봐야 한다.

  • 프롬프트 엔지니어링 할 때 지키면 좋은 사항들

    명확한 목표 설정: 어떤 정보를 얻고자 하는지, 어떤 형식으로 결과를 받고 싶은지 생각하기.
    구체적인 질문: 모호한 질문보다는 세부적인 정보를 포함한 질문이 더 좋은 결과를 이끌어냄.
    맥락 제공: 주제에 대한 간단한 설명이나 상황을 추가하는 등 필요한 배경 정보를 제공하면 더 관련성 높은 답변을 얻을 수 있다.
    실험과 반복: 여러 가지 프롬프트를 시도해 보고, 어떤 방식이 가장 효과적인지 분석하고 수정 / 반복하면서 최적의 프롬프트 찾기.
    예시 제공: 원하는 답변의 형태나 스타일에 대한 예시를 제공하면, 보다 원하는 결과를 얻는 데 도움이 된다.
    제약 조건 설정: 결과에 대한 특정 제약 조건이나 형식을 설정하면 더욱 유용한 답변을 받을 수 있다.
    피드백 활용: 생성된 결과에 대해 피드백을 주고, 이를 바탕으로 프롬프트를 조정하기.

  • 프롬프트 엔지니어링 시 주의사항

모호성 피하기: 애매하거나 일반적인 질문은 피하기.
과도한 정보 제공 자제: 필요한 정보만 제공하고, 너무 많은 배경지식을 넣지 않도록 한다. 정보가 많으면 오히려 혼란을 줄 수 있다.
정확한 언어 사용: 오타나 문법 오류가 있는 경우, 의도와 다른 답변을 얻을 수 있으므로 정확하고 깔끔한 문장을 사용하는 것이 중요합니다.
지속적인 피드백: 결과에 따라 지속적으로 프롬프트를 조정하세요.
정확한 요구사항 명시: 원하는 답변의 형식이나 스타일을 요약, 리스트, 에세이 형식 등으로 요구사항을 구체화하기.


5. 유용한 사이트

/
/

오랜만에 내가 적은 프롬프트 엔지니어링을 보니 잘 쓴듯, 아닌 듯 아리송 하다.
하지만 내가 직접 작성해봤다는 것이 중요하고, 프롬프트 기법은 무궁무진 하다는 점이 참 매력적인 분야다🤗.
개발자는 죽을 때까지 공부가 숙명이라고 하는데, 아직까지는 나에게 천직인듯. 공부할 수 있는 범위가 무제한이라는 점이 사람을 무척 설레게 한다😗✨
(물론 이미지는 영... 싫다. 음성도.........)
지금 이 마음 그대로 또 열심히 공부하자 !!!

profile
🐥삐약이 개발자🐤

0개의 댓글

관련 채용 정보