Tableau’s VizQL Data Service (aka VDS) provides developers with programmatic access to their Tableau Published Data Sources, allowing them to extend their business semantics for any custom workload or application, including AI Agents. The simple_datasource_qa tool adds VDS to the Langchain framework. This notebook shows you how you can use it to build agents that answer analytical questions grounded on your enterprise semantic models.Follow the tableau-langchain project for more tools coming soon!
You can declare your environment variables explicitly, as shown in several cases in this doc. However, if these parameters are not provided, the simple_datasource_qa tool will attempt to automatically read them from environment variables.For the Data Source that you choose to query, make sure you’ve updated the VizqlDataApiAccess permission in Tableau to allow the VDS API to access that Data Source via REST. More info here.
You can declare your environment variables explicitly, as shown in several cases in this cookbook. However, if these parameters are not provided, the simple_datasource_qa tool will attempt to automatically read them from environment variables.For the Data Source that you choose, make sure you’ve updated the VizqlDataApiAccess permission in Tableau to allow the VDS API to access that Data Source via REST. More info here.
Copy
Ask AI
import osfrom dotenv import load_dotenvload_dotenv()tableau_server = "https://stage-dataplane2.tableau.sfdc-shbmgi.svc.sfdcfc.net/" # replace with your Tableau server nametableau_site = "vizqldataservicestage02" # replace with your Tableau sitetableau_jwt_client_id = os.getenv( "TABLEAU_JWT_CLIENT_ID") # a JWT client ID (obtained through Tableau's admin UI)tableau_jwt_secret_id = os.getenv( "TABLEAU_JWT_SECRET_ID") # a JWT secret ID (obtained through Tableau's admin UI)tableau_jwt_secret = os.getenv( "TABLEAU_JWT_SECRET") # a JWT secret ID (obtained through Tableau's admin UI)tableau_api_version = "3.21" # the current Tableau REST API Versiontableau_user = "joe.constantino@salesforce.com" # enter the username querying the target Tableau Data Source# For this cookbook we are connecting to the Superstore dataset that comes by default with every Tableau serverdatasource_luid = ( "0965e61b-a072-43cf-994c-8c6cf526940d" # the target data source for this Tool)model_provider = "openai" # the name of the model provider you are using for your Agent# Add variables to control LLM models for the Agent and Toolsos.environ["OPENAI_API_KEY"] # set an your model API key as an environment variabletooling_llm_model = "gpt-4o-mini"
The initialize_simple_datasource_qa initializes the Langgraph tool called simple_datasource_qa, which can be used for analytical questions and answers on a Tableau Data Source.This initializer function:
Authenticates to Tableau using Tableau’s connected-app framework for JWT-based authentication. All the required variables must be defined at runtime or as environment variables.
Asynchronously queries for the field metadata of the target datasource specified in the datasource_luid variable.
Grounds on the metadata of the target datasource to transform natural language questions into the json-formatted query payload required to make VDS query-datasource requests.
Executes a POST request to VDS.
Formats and returns the results in a structured response.
Copy
Ask AI
# Initialize simple_datasource_qa for querying Tableau Datasources through VDSanalyze_datasource = initialize_simple_datasource_qa( domain=tableau_server, site=tableau_site, jwt_client_id=tableau_jwt_client_id, jwt_secret_id=tableau_jwt_secret_id, jwt_secret=tableau_jwt_secret, tableau_api_version=tableau_api_version, tableau_user=tableau_user, datasource_luid=datasource_luid, tooling_llm_model=tooling_llm_model, model_provider=model_provider,)# load the List of Tools to be used by the Agent. In this case we will just load our data source Q&A tool.tools = [analyze_datasource]
First, we’ll initlialize the LLM of our choice. Then, we define an agent using a langgraph agent constructor class and invoke it with a query related to the target data source.
Copy
Ask AI
from IPython.display import Markdown, displaymodel = ChatOpenAI(model="gpt-4o", temperature=0)tableauAgent = create_react_agent(model, tools)# Run the agentmessages = tableauAgent.invoke( { "messages": [ ( "human", "what's going on with table sales?", ) ] })messages# display(Markdown(messages['messages'][3].content)) #display a nicely formatted answer for successful generations