LlamaIndex 챗 엔진 사용 패턴
LlamaIndex 챗 엔진 사용 패턴 (Usage Pattern)
챗 엔진으로 데이터와 대화하는 실제 패턴을 순서대로 볼게요. 인덱스에서 챗 엔진을 만드는 것부터 시작해요.
시작하기
인덱스에서 챗 엔진을 만들어요.
chat_engine = index.as_chat_engine()
💡 팁: 인덱스 만드는 법은 Indexing 문서를 참고하세요.
데이터와 대화를 시작해요.
response = chat_engine.chat("Tell me a joke.")
대화 히스토리를 리셋해 새 대화를 시작하려면:
chat_engine.reset()
대화형 채팅 REPL에 들어가려면:
chat_engine.chat_repl()
출처: 공식문서
챗 엔진 구성하기
챗 엔진 구성은 쿼리 엔진 구성과 아주 비슷해요.
하이레벨 API
인덱스에서 한 줄로 챗 엔진을 만들고 구성할 수 있어요.
chat_engine = index.as_chat_engine(chat_mode="condense_question", verbose=True)
⚠️ 참고:
chat_mode를 kwarg로 지정하면 다른 챗 엔진에 접근할 수 있어요.condense_question은CondenseQuestionChatEngine,react는ReActChatEngine,context는ContextChatEngine에 대응해요.
⚠️ 참고: 하이레벨 API는 사용 편의성에 최적화되어 있지만, 완전한 범위의 구성 가능성을 노출하지는 않아요.
사용 가능한 챗 모드
best- 쿼리 엔진을 도구로 바꿔서, LLM이 지원하는 것에 따라ReAct데이터 에이전트나OpenAI데이터 에이전트와 함께 사용해요.OpenAI데이터 에이전트는 OpenAI의 함수 호출 API를 쓰기 때문에gpt-3.5-turbo또는gpt-4가 필요해요.condense_question- 채팅 히스토리를 보고 사용자 메시지를 인덱스용 쿼리로 다시 작성해요. 쿼리 엔진의 응답을 읽고 나서 응답을 반환해요.context- 모든 사용자 메시지로 인덱스에서 노드를 검색해요. 검색된 텍스트가 시스템 프롬프트에 삽입돼서, 챗 엔진이 자연스럽게 응답하거나 쿼리 엔진의 맥락을 사용할 수 있어요.condense_plus_context-condense_question과context의 조합이에요. 채팅 히스토리를 보고 사용자 메시지를 인덱스용 검색 쿼리로 다시 작성해요. 검색된 텍스트가 시스템 프롬프트에 삽입돼서, 챗 엔진이 자연스럽게 응답하거나 쿼리 엔진의 맥락을 사용할 수 있어요.simple- 쿼리 엔진 없이 LLM과 직접 단순하게 대화해요.react-best와 같지만ReAct데이터 에이전트를 강제로 사용해요.openai-best와 같지만OpenAI데이터 에이전트를 강제로 사용해요.
로우레벨 조합 API
더 세밀한 제어가 필요하면 로우레벨 조합 API를 쓸 수 있어요. 구체적으로는 index.as_chat_engine(...)을 호출하는 대신 ChatEngine 객체를 직접 생성해요.
⚠️ 참고: API 레퍼런스나 예제 노트북을 확인해야 할 수 있어요.
여기서는 이런 것들을 구성하는 예시예요.
- condense question 프롬프트 구성,
- 기존 히스토리로 대화 초기화,
- verbose 디버그 메시지 출력.
from llama_index.core import PromptTemplate
from llama_index.core.llms import ChatMessage, MessageRole
from llama_index.core.chat_engine import CondenseQuestionChatEngine
custom_prompt = PromptTemplate(
"""\
Given a conversation (between Human and Assistant) and a follow up message from Human, \
rewrite the message to be a standalone question that captures all relevant context \
from the conversation.
<Chat History>
{chat_history}
<Follow Up Message>
{question}
<Standalone question>
"""
)
# list of `ChatMessage` objects
custom_chat_history = [
ChatMessage(
role=MessageRole.USER,
content="Hello assistant, we are having a insightful discussion about Paul Graham today.",
),
ChatMessage(role=MessageRole.ASSISTANT, content="Okay, sounds good."),
]
query_engine = index.as_query_engine()
chat_engine = CondenseQuestionChatEngine.from_defaults(
query_engine=query_engine,
condense_question_prompt=custom_prompt,
chat_history=custom_chat_history,
verbose=True,
)
CondenseQuestionChatEngine은 뒤에 둔 쿼리 엔진과 함께 condense question 방식을 구성하는 대표적인 예다요.
스트리밍
스트리밍을 켜려면 chat 대신 stream_chat 엔드포인트를 호출하면 돼요.
⚠️ 경고: 이 동작은 쿼리 엔진(
streaming=True플래그를 넘기는 방식)과 다소 일관성이 없어요. 일관되게 만드는 작업을 진행 중이에요!
동기 (stream_chat):
chat_engine = index.as_chat_engine()
streaming_response = chat_engine.stream_chat("Tell me a joke.")
for token in streaming_response.response_gen:
print(token, end="")
비동기 (astream_chat):
FastAPI 같은 비동기 프레임워크를 쓸 때는 astream_chat을 사용해요. 호출을 await 해야 하고, 제공되는 비동기 스트리밍 인터페이스(예: async_response_gen() 또는 achat_stream)를 순회해야 해요.
chat_engine = index.as_chat_engine()
streaming_response = await chat_engine.astream_chat("Tell me a joke.")
async for token in streaming_response.async_response_gen():
print(token, end="")