Chat: 인덱스 위의 내장 RAG 에이전트
Chat: 인덱스 위의 내장 RAG 에이전트
검색 API로 조각만 받는 데서 그치지 않고, 질문을 던지면 답까지 만들어 주는 채팅을 붙이고 싶을 때가 있어요. Chat API는 하나 이상의 인덱스 위에서 질문에 답하는 내장 RAG 에이전트를 제공해요. 대화 세션을 관리하고, Server-Sent Events로 응답을 스트리밍하며, 검색·도구 사용·추론까지 내부에서 알아서 처리하죠.
출처: 공식문서
세션 만들기
세션은 대화 이력을 담아요. 생성 시점에 특정 인덱스에 바인딩할 수 있는데, 첫 메시지를 보내면 바인딩된 인덱스가 세션의 수명 동안 잠겨요.
# 특정 인덱스에 바인딩된 세션
session = await client.beta.chat.create(
index_ids=["<index-id-1>", "<index-id-2>"],
)
print(session.session_id)
# 언바인딩 세션 (인덱스는 메시지마다 지정)
session = await client.beta.chat.create()
참고로 한 세션은 최대 10개 인덱스에 바인딩할 수 있고, 매 턴마다 바인딩된 모든 인덱스로 검색이 팬아웃돼요.
메시지 스트리밍
메시지를 보내면 에이전트의 응답이 Server-Sent Events 스트림으로 돌아와요. 이 스트림에는 사고(thinking) 단계, 도구 호출(검색), 그리고 최종 텍스트 응답이 포함돼요.
이벤트를 줄 단위로 파싱하려면 각 SDK가 원시 응답 접근자를 제공해요 — Python은 with_streaming_response, TypeScript는 .asResponse(), Go는 option.WithResponseBodyInto, Java는 withRawResponse()예요.
import json
response = client.beta.chat.with_streaming_response.stream(
session.session_id,
index_ids=["<index-id>"],
prompt="What are the key findings in the Q3 report?",
)
async with response as stream:
async for line in stream.iter_lines():
if not line or line.startswith(":"):
continue
if line.startswith("data: "):
data = json.loads(line[6:])
if data.get("type") == "text_delta":
print(data["content"], end="", flush=True)
elif data.get("type") == "stop":
print("\n--- Done ---")
else:
print(data) # handle other event types as needed
CLI(llp beta:chat stream)는 예외로, 한 턴 전체를 버퍼링하고 에이전트가 끝나면 누적된 이벤트 페이로드를 출력해요. 턴을 점검하는 데는 유용하지만 실시간 자바스크립트 델타 렌더링에는 안 맞아요.
이벤트 타입
스트림은 두 종류의 이벤트를 내보내요.
델타 이벤트 (event: delta) — 실시간 표시용 증분 콘텐츠:
| 타입 | 설명 |
|---|---|
text_delta |
에이전트 응답 텍스트의 일부. |
thinking_delta |
에이전트 추론의 일부 (노출된 경우). |
메시지 이벤트 (event: message) — 완결된 개별 이벤트:
| 타입 | 설명 |
|---|---|
text |
완전한 에이전트 응답 텍스트. |
thinking |
완전한 에이전트 추론 블록. |
user_input |
사용자의 원래 메시지. |
tool_call |
에이전트의 도구 호출 (예: 검색). |
tool_result |
도구 호출의 결과. |
stop |
스트림 종료, 토큰 사용량 포함. |
warning |
정보성 경고 (예: 건너뛴 인덱스). |
세션 목록·상세·삭제
세션은 목록으로 조회하고, 요약만 또는 전체 이벤트 이력으로 상세를 열어볼 수 있어요.
# 목록
sessions = await client.beta.chat.list()
for s in sessions.items:
print(f"{s.session_id}: {s.generated_title or '(untitled)'}")
# 요약만
summary = await client.beta.chat.get_summary(session.session_id)
print(summary.generated_title)
# 전체 세션 (이벤트 이력 포함)
full = await client.beta.chat.retrieve(session.session_id)
for event in full.events:
print(event.type, event.content[:100] if hasattr(event, "content") else "")
# 삭제
await client.beta.chat.delete(session.session_id)
더 알아보기
- Index 시작 가이드 — 인덱스 만들기부터 검색까지
- Retrieval — 하이브리드 검색 파라미터와 리랭킹