04-langchain-chat

2024. 1. 13. 14:39langchain

!python3 -m venv langchain
!source langchain/bin/activate
!pip install -U langchain openai
In [ ]:
from getpass import getpass

# enter your api key
OPENAI_API_KEY = getpass()

ChatOpenAI 개체를 초기화합니다. 무작위성을 최소화하고 출력이 반복 가능하도록 temperature=0으로 설정하겠습니다.

In [ ]:
from langchain.chat_models import ChatOpenAI
llm = ChatOpenAI(
    temperature=0, 
    openai_api_key=OPENAI_API_KEY,
    model_name='gpt-3.5-turbo'  # can be used with llms like 'text-davinci-003'
)
In [ ]:
from langchain.chat_models import ChatOpenAI

chat = ChatOpenAI(
    openai_api_key=OPENAI_API_KEY,
    temperature=0,
    model='gpt-3.5-turbo'
)

Chat-GPT 모델을 사용한 채팅gpt-3.5-turbo은 일반적으로 다음과 같이 구성됩니다.

System: You are a helpful assistant.

User: Hi AI, how are you today?

Assistant: I'm great thank you. How can I help you?

User: I'd like to understand string theory.

Assistant:

응답이 없는 마지막 "Assistant:"은 모델이 대화를 계속하도록 유도하는 것입니다. 공식 OpenAI ChatCompletion 엔드포인트에서는 다음과 같은 형식으로 모델에 전달됩니다.

[ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "Hi AI, how are you today?"}, {"role": "assistant", "content": "I'm great thank you. How can I help you?"} {"role": "user", "content": "I'd like to understand string theory."} ]

LangChain에는 약간 다른 형식이 있습니다. 다음과 같이 3개의 메시지 개체를 사용합니다.

In [ ]:
from langchain.schema import (
    SystemMessage,
    HumanMessage,
    AIMessage
)

messages = [   
    SystemMessage(content="당신은 도움이 되는 도우미입니다."),
    HumanMessage(content="안녕 AI, 오늘 어떠세요?"),
    AIMessage(content="정말 감사합니다. 어떻게 해 드릴까요? 무엇을 도와 드릴까요?"),
    HumanMessage(content="끈 이론을 이해하고 싶습니다.")
]

형식은 매우 유사합니다. "user"의 역할을 HumanMessage로 바꾸고 "assistant"의 역할을 AIMessage으로 바꾸는 것뿐입니다.

이러한 메시지를 ChatOpenAI 객체에 전달하여 AI에서 다음 응답을 생성합니다.

In [ ]:
res = chat(messages)
res

이에 대한 응답으로 우리는 또 다른 AI 메시지 객체를 얻습니다.

In [ ]:
print(res.content)

res은 또 다른 AIMessage 개체이므로 messages에 추가하고 다른 개체를 추가할 수 있습니다 HumanMessage 대화에서 다음 응답을 생성합니다.

In [ ]:
# add latest AI response to messages
messages.append(res)

# now create a new user prompt
prompt = HumanMessage(
    content="Why do physicists believe it can produce a 'unified theory'?"
)
# add to messages
messages.append(prompt)

# send to chat-gpt
res = chat(messages)

print(res.content)

새로운 프롬프트 템플릿

지금까지 본 것 외에 사용할 수 있는 세 가지 새로운 프롬프트 템플릿도 있습니다. SystemMessagePromptTemplate, AIMessagePromptTemplate 및 HumanMessagePromptTemplate입니다.

이것은 단순히 반환되는 "프롬프트"를 수정하는 Langchain의 프롬프트 템플릿의 확장입니다. 각각 SystemMessage, AIMessage 또는 HumanMessage 개체가 됩니다.

현재로서는 이러한 개체에 대한 사용 사례가 많지 않습니다. 하지만 메시지에 추가하고 싶은 내용이 있으면 도움이 될 수 있습니다. 예를 들어, AI 응답이 항상 50자 이하로 구성되기를 원한다고 가정해 보겠습니다.

In [ ]:
chat = ChatOpenAI(
    openai_api_key=OPENAI_API_KEY,
    temperature=0,
    model='gpt-3.5-turbo-0301'
)

# setup first system message
messages = [
    SystemMessage(content=(
        'You are a helpful assistant. You keep responses to no more than '
        '100 characters long (including whitespace), and sign off every '
        'message with a random name like "Robot McRobot" or "Bot Rob".'
    )),
    HumanMessage(content="Hi AI, how are you? What is quantum physics?")
]

이제 첫 번째 완성을 해보세요.

res = chat(messages)

print(f"Length: {len(res.content)}\n{res.content}")

현재 OpenAI gpt-3.5-turbo-0301 모델을 사용하면 첫 번째 시스템 메시지에서만 이 명령을 전달하는 경우 문제가 발생할 수 있습니다. AI 도우미가 지시 사항을 잘 따르지 못하는 것 같습니다. HumanMessagePromptTemplate를 통해 HumanMessage에 이러한 지침을 추가하면 어떻게 될까요?

In [ ]:
from langchain.prompts.chat import HumanMessagePromptTemplate, ChatPromptTemplate

human_template = HumanMessagePromptTemplate.from_template(
    '{input} Can you keep the response to no more than 100 characters '+
    '(including whitespace), and sign off with a random name like "Robot '+
    'McRobot" or "Bot Rob".'
)

# create the human message
chat_prompt = ChatPromptTemplate.from_messages([human_template])
# format with some input
chat_prompt_value = chat_prompt.format_prompt(
    input="Hi AI, how are you? What is quantum physics?"
)
chat_prompt_value

HumanMessagePromptTemplate을 .format_prompt 메소드와 함께 일반적인 프롬프트 템플릿으로 사용하려면 이를 ChatPromptTemplate 객체. 이는 새로운 채팅 기반 프롬프트 템플릿 모두에 해당됩니다. 를 경유하여 전달할 필요가 있습니다. 이것은 모든 챕봇 베이스된 프롬프트 템플릿의 경우입니다. 이를 사용하여 ChatPromptValue 개체를 반환합니다. 다음과 같이 목록이나 문자열 형식으로 지정할 수 있습니다.

In [ ]:
chat_prompt_value.to_messages()
In [ ]:
chat_prompt_value.to_string()

이 새로운 접근 방식이 효과가 있는지 살펴보겠습니다.

In [ ]:
messages = [
    SystemMessage(content=(
        'You are a helpful assistant. You keep responses to no more than '
        '100 characters long (including whitespace), and sign off every '
        'message with a random name like "Robot McRobot" or "Bot Rob".'
    )),
    chat_prompt.format_prompt(
        input="Hi AI, how are you? What is quantum physics?"
    ).to_messages()[0]
]

res = chat(messages)

print(f"Length: {len(res.content)}\n{res.content}")

이번에는 글자 수가 꽤 가까워졌고 글자 수 제한(8 글자)을 약간 초과했으며 Bot Rob에게 승인을 받았습니다.

또한 챗봇이 따라야 할 몇 가지 예(예를 통한 몇 번의 훈련)와 함께 초기 시스템 메시지를 구축하기 위해 프롬프트 템플릿 접근 방식을 사용할 수도 있습니다.

In [ ]:
from langchain.prompts.chat import (
    SystemMessagePromptTemplate,
    AIMessagePromptTemplate
)

system_template = SystemMessagePromptTemplate.from_template(
    'You are a helpful assistant. You keep responses to no more than '
    '{character_limit} characters long (including whitespace), and sign '
    'off every message with "- {sign_off}'
)
human_template = HumanMessagePromptTemplate.from_template("{input}")
ai_template = AIMessagePromptTemplate.from_template("{response} - {sign_off}")

# create the list of messages
chat_prompt = ChatPromptTemplate.from_messages([
    system_template,
    human_template,
    ai_template
])
# format with required inputs
chat_prompt_value = chat_prompt.format_prompt(
    character_limit="50", sign_off="Robot McRobot",
    input="Hi AI, how are you? What is quantum physics?",
    response="Good! It's physics of small things"
)
chat_prompt_value

우리는 이를 메시지로 추출하여 다음 쿼리와 함께 채팅 모델에 제공합니다. 그러면 평소와 같이(템플릿 없이) 피드됩니다.

In [ ]:
messages = chat_prompt_value.to_messages()

messages.append(
    HumanMessage(content="How small?")
)

res = chat(messages)

print(f"Length: {len(res.content)}\n{res.content}")

완벽합니다. 몇 가지 더 시도해 보겠습니다.

In [ ]:
# add last response
messages.append(res)

# make new query
messages.append(
    HumanMessage(content="Okay cool, so it is like 'partical physics'?")
)

res = chat(messages)

print(f"Length: {len(res.content)}\n{res.content}")

저희는 약간 초과하였습니다. 다음과 같이 이전 HumanMessagePromptTemplate을 다시 사용할 수 있습니다.

In [ ]:
from langchain import PromptTemplate

# this is a faster way of building the prompt via a PromptTemplate
human_template = HumanMessagePromptTemplate.from_template(
    '{input} Answer in less than {character_limit} characters (including whitespace).'
)
# create the human message
human_prompt = ChatPromptTemplate.from_messages([human_template])
# format with some input
human_prompt_value = human_prompt.format_prompt(
    input="Okay cool, so it is like 'partical physics'?",
    character_limit="50"
)
human_prompt_value
In [ ]:
# drop the last message about partical physics so we can rewrite
messages.pop(-1)
In [ ]:
messages.extend(human_prompt_value.to_messages())
messages

이제 다음을 처리합니다.

In [ ]:
res = chat(messages)

print(f"Length: {len(res.content)}\n{res.content}")

또 좋은 답변이군요!

이제 위의 모든 사항이 다음과 같은 단순한 f-문자열보다 나은지에 대해 논쟁의 여지가 있습니다.

In [ ]:
_input = "Okay cool, so it is like 'partical physics'?"
character_limit = 50

human_message = HumanMessage(content=(
    f"{_input} Answer in less than {character_limit} characters "
    "(including whitespace)."
))

human_message_input = "Okay cool, so it is like 'partical physics'?"
character_limit = 50

human_message = HumanMessage(content=(
    f"{_input} Answer in less than {character_limit} characters "
    "(including whitespace)."
))

human_message

이 예에서는 위의 내용이 훨씬 간단합니다.

In [ ]:
# drop the last message about partical physics so we can rewrite
messages.pop(-1)

# add f-string formatted message
messages.append(human_message)
messages
In [ ]:
res = chat(messages)

print(f"Length: {len(res.content)}\n{res.content}")

이것이 LangChain의 새로운 채팅 기능을 살펴보는 예입니다.

In [ ]:
출처 : https://github.com/pinecone-io/examples/blob/master/learn/generation/langchain/handbook/04-langchain-chat.ipynb

'langchain' 카테고리의 다른 글

09-langchain-streaming  (0) 2024.01.15
06-langchain-agents  (1) 2024.01.14
03a-token-counter  (0) 2024.01.12
03-langchain-conversational-memory  (2) 2024.01.11
02-langchain-체인  (1) 2024.01.10