에이전트 응답을 시각화로 렌더링

Conversational Analytics API는 사용자 질문을 기반으로 하는 대화형 시각화를 생성할 수 있습니다. API는 차트를 Vega-Lite JSON 구성 또는 SVG 이미지 (Looker 데이터 소스의 경우 v1alphav1beta API 버전에서만)로 반환합니다. 에이전트에게 특정 요구사항이 있는 차트를 생성하도록 지시할 수도 있습니다. 시각화는 사용자 질문에 대한 응답으로 얻은 데이터 결과를 사용하여 생성됩니다.

캘리포니아에서 20~30대와 40~50대 연령대의 바지 총 판매가와 주문 수를 보여주는 막대 그래프

영역 차트에는 지난 12개월 동안의 월별 총 판매가 실적이 표시되어 있으며, 최고치는 3,395.12달러이고 평균은 2,517.68달러입니다.

지원되는 시각화

API는 Vega-Lite를 사용하여 시각화를 만들고 모든 표준 Vega-Lite 기능을 지원합니다. 다음 차트 유형이 지원됩니다.

  • 영역
  • 막대
  • 지리적 도형
  • 히트맵
  • 선 (시계열)
  • 원형
  • 분산형

차트 생성 방법

에이전트는 관련 데이터 결과를 식별하고 이를 하위 에이전트에 전달합니다. 이 하위 에이전트는 Python 코드를 실행하여 차트의 Vega-Lite JSON 구성을 생성합니다. API는 대화 컨텍스트를 사용하여 차트를 생성할 때 사용자의 의도를 더 잘 파악합니다. API는 Python을 활용하여 더 복잡한 차트를 만들 수 있습니다.

에이전트는 차트의 관련성과 가독성을 높이기 위해 집계 또는 필터 적용과 같은 사소한 데이터 변환을 실행할 수 있습니다.

출력 형식

차트는 chart 결과 메시지로 반환되며 다음 형식으로 제공될 수 있습니다.

컨텍스트의 ChartOptions 필드를 사용하여 이미지를 요청할 수 있습니다. 이미지가 요청되면 API는 이미지와 Vega-Lite JSON 출력을 모두 제공합니다.

에이전트 응답을 시각화로 렌더링

이 섹션에서는 Python SDK를 사용하여 Conversational Analytics API 응답에 제공된 차트 사양에서 시각화를 렌더링하는 방법을 보여줍니다. 샘플 코드는 응답의 chart 필드에서 차트 사양(Vega-Lite 형식)을 추출하고 Vega-Lite를 기반으로 빌드된 Altair 라이브러리를 사용하여 차트를 렌더링하고 이미지로 저장한 후 표시합니다.

Vega-Lite 및 Vega-Lite 생태계를 사용하여 차트를 렌더링하는 방법에 대한 자세한 내용은 Vega-Lite 시각화 작성 도구를 참고하세요.

예: Vega-Lite 출력에서 차트 렌더링

이 예시에서는 Conversational Analytics API 에이전트 응답에서 막대 그래프를 렌더링하는 방법을 보여줍니다. 이 예시에서는 다음 프롬프트와 함께 요청을 전송합니다.

"Create a bar graph that shows the top five states by the total number of airports."

샘플 코드는 다음 도우미 함수를 정의합니다.

  • render_chart_response: chart 메시지에서 Vega-Lite 구성을 추출하고 Altair 라이브러리에서 사용할 수 있는 형식으로 변환한 후 차트를 렌더링하고 chart.png에 저장한 후 표시합니다.
  • chat: inline_context 변수와 현재 messages 목록을 사용하여 Conversational Analytics API에 요청을 전송하고 스트리밍 응답을 처리하며 차트가 반환되면 render_chart_response를 호출하여 표시합니다.

다음 샘플 코드를 사용하려면 다음을 바꾸세요.

  • sqlgen-testing: 필요한 API를 사용 설정한 결제 프로젝트의 ID입니다.
  • Create a bar graph that shows the top five states by the total number of airports: Conversational Analytics API에 전송할 프롬프트입니다.
from google.cloud import geminidataanalytics
from google.protobuf.json_format import MessageToDict
import altair as alt
import proto

# Helper function for rendering chart response
def render_chart_response(resp):
  def _convert(v):
    if isinstance(v, proto.marshal.collections.maps.MapComposite):
      return {k: _convert(val) for k, val in v.items()}
    elif isinstance(v, proto.marshal.collections.RepeatedComposite):
      return [_convert(el) for el in v]
    elif isinstance(v, (int, float, str, bool, type(None))):
      return v
    else:
      return MessageToDict(v)

  try:
    vega_config = _convert(resp.result.vega_config)
    chart = alt.Chart.from_dict(vega_config)
    chart.save('chart.png')
    chart.display()
    print("Chart rendered and saved as chart.png")
  except Exception as e:
    print(f"Error rendering chart: {e}")

# Helper function for calling the API
def chat(q: str, inline_context, messages):
  billing_project = "sqlgen-testing"

  input_message = geminidataanalytics.Message(
      user_message=geminidataanalytics.UserMessage(text=q)
  )
  messages.append(input_message)

  client = geminidataanalytics.DataChatServiceClient()
  request = geminidataanalytics.ChatRequest(
      inline_context=inline_context,
      parent=f"projects/{billing_project}/locations/global",
      messages=messages,
  )

  # Make the request
  try:
    stream = client.chat(request=request)

    for reply in stream:
      if reply.system_message and hasattr(reply.system_message, 'chart'):
        # ChartMessage includes `query` for generating a chart and `result` with the generated chart.
        if hasattr(reply.system_message.chart, 'result'):
          print("Chart result found in response.")
          render_chart_response(reply.system_message.chart)
        else:
          print("Chart message found, but no result yet.")
      # Append system messages to maintain context for follow-up turns
      if reply.system_message:
          messages.append(geminidataanalytics.Message(system_message=reply.system_message))

  except Exception as e:
    print(f"Error calling API: {e}")

# Example Usage:
# Assuming 'inline_context' and 'messages' are initialized as per "Build a data agent using the Python SDK"
# Example initialization (replace with your actual context and message history):
# inline_context = geminidataanalytics.InlineContext(...)
# messages = []

# Send the prompt to make a bar graph
chat("Create a bar graph that shows the top five states by the total number of airports")