BookmarkSubscribeRSS Feed

How to Create Your Custom LangChain Agent for SAS Viya

Started ‎02-09-2024 by
Modified ‎02-09-2024 by
Views 878

In a previous post, GPT-4 Assisted Data Management in SAS Viya: A Custom LangChain Agent Approach, we discussed an agent using GPT-4, LangChain, and SASPY for data management in SAS Viya. This agent performed tasks like getting table info, column details, and table manipulation. Now, we'll discuss how to create such a smart agent.

 

The Big Picture

 

In simple terms, LangChain matches the user's intent with the best custom tool. This tool then interacts with SAS Viya.

 

bt_1_SAS_Viya_Custom_Agent_LangChain_User_Asks.png

Select any image to see a larger version.
Mobile users: To view the images, select the "Full" version at the bottom of the page.

 

After this, the log is returned and a response is created by the large language model (LLM). If you haven't already, check out the video in the previous article, GPT-4 Assisted Data Management in SAS Viya: A Custom LangChain Agent Approach, for more information.

 

bt_2_SAS_Viya_Custom_Agent_LangChain_LLM_Responds.png

 

Now let's look at what you need to build this custom agent.

 

Components

 

SAS Viya Environment

 

You will need a SAS Viya deployment. From your SAS Viya deployment you will need:

  • The SAS Viya URL.
  • A SAS username.
  • The SAS user's password.

 

Azure OpenAI

 

You need to create a resource and deploy a model. To make a call successfully against Azure OpenAI, you need an endpoint, a key, and a deployment.

Visual Studio Code

 

If you're a regular user of Visual Studio Code, great.

 

Python Requirements

 

Create a requirements.txt file that includes these Python packages:

 

saspy
langchain
langchain_openai
pandas

 

Azure OpenAI Configuration

 

Create a 'config.py' file in a folder to hold the Azure OpenAI configuration.

 

azure_openai_endpoint =  'https://resource-name.openai.azure.com/' # your endpoint should look like https://YOUR_RESOURCE_NAME.openai.azure.com/
api_key = 'fill_in_here' # your key looks like 932e...a99
api_version = '2023-07-01-preview'

 

You'll refer back to this program later in the sastools_mem.py program using 'import config'. 

 

Setup SASPY

 

We'll use SASPY to send programs from a Python program to a SAS Viya instance. We'll use SASPY in the custom SAS Viya tools that we'll create in the main Python program. Ajmal Farzam has already given a brief explanation of SASPY in his article Submit workloads to SAS Viya from Python. I've used his guidelines to create two files:

 

sascfg_personal.py

 

Create a sascfg_personal.py file that contains a profile, the SAS Viya URL and the name of the authkey, among other details.

 

SAS_config_names=['httpsviya']
SAS_config_options = {'lock_down': False,
                      'verbose'  : True,
                      'prompt'   : True
                     }
SAS_output_options = {'output' : 'html5'}       # not required unless changing any of the default
httpsviya = {'ip'      : 'my_sas_viya_URL.sas.com',
             'context' : 'SAS Studio compute context',
             'authkey' : 'HTTP_Dev',
             'options' : ["fullstimer", "memsize=4G"]
             }

 

authinfo

 

SASPY is reading the credentials from an authinfo file:

 

Windows: Create a _authinfo file in C:\Users\myuser. The first word must match the authkey in the sascfg_personal.py file.

 

HTTP_Dev user SAS_USER password SAS_Pass_Value

 

Linux: you should create a .authinfo file in /home/myuser. Read more about it in the SASPY documentation / authinfo.

 

Optional: Create a Program to Test SASPY Connection

 

For example:

 

import sys
sys.path
import saspy

# display active session

sas = 'No active SAS session!'
print(sas)

# create _authinfo file in C:\Users\sbxbot
if sas == 'No active SAS session!':
    sas = saspy.SASsession(cfgfile='sascfg_personal.py', cfgname = 'httpsviya')
else:
    print ('There is a SAS session')
print(sas)
print(type(sas))

 

LangChain Custom Agent for SAS Viya Operations

 

The sastools_mem.py is our main Python program. It makes a LangChain custom agent that interacts with SAS tables in SAS Viya, carries out specific tasks, and provides answers based on those tasks.

 

# LangChain custom SAS Viya agent WITH memory
##############################################

# Resource: https://python.langchain.com/docs/modules/agents/how_to/custom_agent

# Load the LLM
import os
import urllib3
urllib3.disable_warnings

## A Large Language Model - Azure OpenAI
from langchain_openai import AzureChatOpenAI

## Setting Azure OpenAI environment variables
import config
os.environ["OPENAI_API_TYPE"] = "azure"
os.environ["OPENAI_API_KEY"] = config.api_key
os.environ["AZURE_OPENAI_ENDPOINT"] = config.azure_openai_endpoint
os.environ["OPENAI_API_VERSION"] = config.api_version

## GPT-4 as deployment
llm = AzureChatOpenAI(deployment_name="gpt-4", temperature=0, max_tokens=2000)

# Define tools
# SAS - see https://communities.sas.com/t5/SAS-Communities-Library/Submit-workloads-to-SAS-Viya-from-Python/ta-p/807263
# non-SAS, such as get_word_length for control

from langchain.agents import tool, Tool

@tool
def get_word_length(word: str) -> int:
    """Returns the length of a word. Useful when you need to calculate the length of a word or string. This will return the length as an integer."""
    return len(word)


def get_table_information(library_table: str) -> str:
    """Returns detailed table description for a SAS table. Accepts two inputs, table and library. Useful when you need to get detailed information about a SAS table or data set from a SAS library. This will return the columns, the number of rows, statistics about the table."""
    # SASPY auth and start session
    import saspy
    sas = saspy.SASsession(cfgfile='sascfg_personal.py', cfgname = 'httpsviya')
    table = library_table.strip().split('.')[-1]
    library = library_table.strip().split('.')[0]
    sas_code = f"PROC CONTENTS DATA={library}.{table};run;quit;"
    sas_submit = sas.submit(sas_code)
    # Display results
    return (sas_submit['LOG'])


def get_column_info_table(library_table: str) -> str:
    """Returns information about the columns in a SAS table. Useful when you need to get detailed information about a SAS table or data set from a SAS library. This will return the result of PROC CONTENTS on the table."""
    # SASPY auth and start session
    import saspy
    table = library_table.split('.')[-1]
    library = library_table.split('.')[0]
    sas = saspy.SASsession(cfgfile='sascfg_personal.py', cfgname = 'httpsviya')
    table = sas.sasdata(table, library)
    # DESCRIBE TABLE
    return (table.columnInfo())


def append_table(library_table: str) -> str:
    """Returns an appended table from two SAS tables or data sets. This is useful when you need to append two tables from SAS libraries. This will create a SAS data set called NEW in the SASDM library."""
    # SASPY auth and start session
    import saspy
    sas = saspy.SASsession(cfgfile='sascfg_personal.py', cfgname = 'httpsviya')
    base = library_table.strip().split(',')[0]
    appended = library_table.strip().split(',')[-1]
    sas_code = f"data sasdm.new; set {base};run; proc append base=sasdm.new data={appended} force; run; quit;"
    sas_submit = sas.submit(sas_code)
    # Display results
    return (sas_submit['LOG'])


tools = [
    Tool(
        name = "get_word_length",
        func = get_word_length,
        description = "Useful when you need to calculate the length of a word or string. This will return the length."
    ),
     Tool(
        name = "get_table_information",
        func = get_table_information,
        description = "Useful when you need to get detailed information about a SAS table or data set from a SAS library. This will return the columns, the number of rows, statistics about the table."
     ),
    Tool(
        name = "get_column_info_table",
        func = get_column_info_table,
        description = "Useful when you need to get detailed information about a SAS table, at a column level. This will return the columns, the number of rows, statistics about the table."
     ),
    Tool(
        name = "append_table",
        func = append_table,
        description = "Returns an appended table from two SAS tables or data sets. This is useful when you need to append two tables from SAS libraries. This will create a SAS data set called NEW in the SASDM library."
     )
        ]


# Create Prompt
## Now let us create the prompt. Because OpenAI Function Calling is finetuned for tool usage, we hardly need any instructions on how to reason, or how to output format.
## We will just have two input variables: input and agent_scratchpad. input should be a string containing the user objective.
## agent_scratchpad should be a sequence of messages that contains the previous agent tool invocations and the corresponding tool outputs.

# Add Memory

## Add a place for memory variables to go in the prompt
## Keep track of the chat history
## First, let’s add a place for memory in the prompt. We do this by adding a placeholder for messages with the key "chat_history". Notice that we put this ABOVE the new user input (to follow the conversation flow).

from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder

MEMORY_KEY = "chat_history"
prompt = ChatPromptTemplate.from_messages(
    [
        (
            "system",
            """You are a world class Data Engineer, who can do detailed research using SAS.

            Please make sure you complete the objective above with the following rules:
            1/ Your job is to first breakdown the topic into relevant questions for understanding the topic in detail. You should have at max only 3 questions not more than that, in case there are more than 3 questions consider only the first 3 questions and ignore the others.
            2/ You should use the get table information or get column info tools to get more information about a given topic. You are allowed to use these tools only 3 times in this process.
            3/ Perform the operations demanded by the user, such as append, merge, etc. using the appropriate tools.""",
        ),
        MessagesPlaceholder(variable_name=MEMORY_KEY),
        ("user", "{input}"),
        MessagesPlaceholder(variable_name="agent_scratchpad"),
    ]
)

# Bind tools to LLM
## How does the agent know what tools it can use? In this case we’re relying on OpenAI function calling LLMs, which take functions as a separate argument and have been specifically trained to know when to invoke those functions.
## To pass in our tools to the agent, we just need to format them to the OpenAI function format and pass them to our model. (By bind-ing the functions, we’re making sure that they’re passed in each time the model is invoked.)

from langchain_community.tools.convert_to_openai import format_tool_to_openai_function

llm_with_tools = llm.bind(functions=[format_tool_to_openai_function(t) for t in tools])

# Create the Agent
## Putting those pieces together, we can now create the agent. We will import two last utility functions: a component for formatting intermediate steps (agent action, tool output pairs) to input messages that can be sent to the model, and a component for converting the output message into an agent action/agent finish.

from langchain.agents.format_scratchpad import format_to_openai_function_messages
from langchain.agents.output_parsers import OpenAIFunctionsAgentOutputParser

## We can then set up a list to track the chat history

from langchain_core.messages import AIMessage, HumanMessage

chat_history = []

agent = (
    {
        "input": lambda x: x["input"],
        "agent_scratchpad": lambda x: format_to_openai_function_messages(
            x["intermediate_steps"]
        ),
        "chat_history": lambda x: x["chat_history"],
    }
    | prompt
    | llm_with_tools
    | OpenAIFunctionsAgentOutputParser()
)

from langchain.agents import AgentExecutor

agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

# ASK QUESTIONS

## Control
q = 'How many letters in the word SASDM?'
print('\nI will ask: ', q, '\n')

result = agent_executor.invoke({"input": q, "chat_history": chat_history})
chat_history.extend(
    [
        HumanMessage(content=q),
        AIMessage(content=result["output"]),
    ]
)
q = 'Is that a real word?'
print('\nI will ask: ', q, '\n')
agent_executor.invoke({"input": q, "chat_history": chat_history})


## SAS Viya

q = 'Can you get column information for the SAS table PRDSAL2 from the SASHELP SAS library?'
print('\nI will ask: ', q, '\n')

result = agent_executor.invoke({"input": q, "chat_history": chat_history})
chat_history.extend(
    [
        HumanMessage(content=q),
        AIMessage(content=result["output"]),
    ]
)

q = 'Are there any columns containing date or period of time?'
print('\nI will ask to test memory: ', q, '\n')
agent_executor.invoke({"input": q, "chat_history": chat_history})


q = 'Append the table PRDSAL2 from SASHELP library to the table PRDSAL3 from SASHELP library'
print('\nI will ask: ', q, '\n')

result = agent_executor.invoke({"input": q, "chat_history": chat_history})
chat_history.extend(
    [
        HumanMessage(content=q),
        AIMessage(content=result["output"]),
    ]
)
q = 'How many rows again?'
print('\nI will ask to test memory: ', q, '\n')
agent_executor.invoke({"input": q, "chat_history": chat_history})

q = 'Provide detailed table description for table NEW from SASDM library'
print('\nI will ask: ', q, '\n')

result = agent_executor.invoke({"input": q, "chat_history": chat_history})
chat_history.extend(
    [
        HumanMessage(content=q),
        AIMessage(content=result["output"]),
    ]
)

q = 'In what library is stored that table?'
print('\nI will ask to test memory: ', q, '\n')
agent_executor.invoke({"input": q, "chat_history": chat_history})

 

Importing Libraries

 

Initially, the script imports necessary Python libraries and loads the Large Language Model (LLM) from LangChain. AzureChatOpenAI from the langchain_openai library is used as the LLM. The script sets up the necessary environment variables for Azure OpenAI using a config file.

 

 

import os
import urllib3
from langchain_openai import AzureChatOpenAI
import config
...

 

Defining Tools

 

The script defines several tools, which are Python functions to perform certain tasks. These tools help in working with SAS tables. They can fetch table information, fetch column information, and append tables.

 

from langchain.agents import tool, Tool

@tool
def get_word_length(word: str) -> int:
    """Returns the length of a word."""
    ...
def get_table_information(library_table: str) -> str:
    """Returns detailed table description for a SAS table."""
    ...
def get_column_info_table(library_table: str) -> str:
    """Returns information about the columns in a SAS table."""
    ...
def append_table(library_table: str) -> str:
    """Returns an appended table from two SAS tables or data sets. This is useful when you need to append two tables from SAS libraries. This will create a SAS data set called NEW in the SASDM library."""
    # SASPY auth and start session
    import saspy
    sas = saspy.SASsession(cfgfile='sascfg_personal.py', cfgname = 'httpsviya')
    base = library_table.strip().split(',')[0]
    appended = library_table.strip().split(',')[-1]
    sas_code = f"data sasdm.new; set {base};run; proc append base=sasdm.new data={appended} force; run; quit;"
    sas_submit = sas.submit(sas_code)
    # Display results
    return (sas_submit['LOG'])

 

The append_table tool does the following:

  • It imports SASPY.
  • It starts a SAS session by linking to the SAS Studio compute context, which was defined in the sascfg_personal.py file.
  • It parses the 'library_table' variable, whose value is given by the LLM.
  • It executes the SAS code with the parsed arguments, in a SAS session SASPY creates.

 

Note: We specify the name of the table to be created, just to verify the results. The name can be another parameter, sure.

 

Creating the Agent

 

After defining the tools, the script creates an agent using the LangChain API. This agent uses the OpenAI GPT-4 model and is linked with the tools defined earlier. The agent gets a prompt template which guides it on how to interact with the user.

 

from langchain_community.tools.convert_to_openai import format_tool_to_openai_function
...
from langchain.agents.format_scratchpad import format_to_openai_function_messages
from langchain.agents.output_parsers import OpenAIFunctionsAgentOutputParser
...
from langchain.agents import AgentExecutor
...

 

Running the Agent

 

Finally, the script runs the agent by asking a series of questions. There are SAS and non-SAS questions. The latter are used for control:

 

  • How many letters in the word SASDM? (non-SAS)
  • Is that a real word? (non-SAS)
  • Can you get column information for the SAS table PRDSAL2 from the SASHELP SAS library?
  • Are there any columns containing date or period of time?
  • Append the table PRDSAL2 from SASHELP library to the table PRDSAL3 from SASHELP library
  • How many rows again?
  • Provide detailed table description for table NEW from SASDM library
  • In what library is the table stored?

 

The function agent_executor.invoke() is used to communicate with the agent and obtain its responses. The chat history is stored and used as context for future questions.

 

from langchain_core.messages import AIMessage, HumanMessage
...
q = 'Append the table PRDSAL2 from SASHELP library to the table PRDSAL3 from SASHELP library'
print('\nI will ask: ', q, '\n')
...
result = agent_executor.invoke({"input": q, "chat_history": chat_history})
...
q = 'How many rows again?'
agent_executor.invoke({"input": q, "chat_history": chat_history})

 

Summary

 

In short, this Python script sets up a custom LangChain agent. This agent can handle detailed operations on SAS tables and respond to user questions based on those operations.

 

Run the Python Program

 

In a Bash terminal type:

 

pip install -r requirements.txt
python sastools_mem.py

 

Interpreting the Execution Logs

 

This section provides an extract of the full log generated by the running Python program:

 

I will ask:  Can you get column information for the SAS table PRDSAL2 from the SASHELP SAS library?
> Entering new AgentExecutor chain...
Invoking: `get_column_info_table` with `SASHELP.PRDSAL2`

SAS server started using Context SAS Studio compute context with SESSION_ID=4768a27c-0826-496e-8693-c67e26bc5aab-ses0000
             Member   Num  Variable  Type   Len    Pos      Format Informat            Label
0   SASHELP.PRDSAL2   4.0    ACTUAL   Num   8.0    0.0  DOLLAR12.2      NaN     Actual Sales
1   SASHELP.PRDSAL2   1.0   COUNTRY  Char  10.0   48.0    $CHAR10.      NaN          Country
2   SASHELP.PRDSAL2   3.0    COUNTY  Char  20.0   80.0    $CHAR20.      NaN           County
3   SASHELP.PRDSAL2  10.0     MONTH   Num   8.0   32.0   MONNAME3.      NaN            Month
4   SASHELP.PRDSAL2  11.0     MONYR   Num   8.0   40.0      MONYY.   MONYY.       Month/Year
5   SASHELP.PRDSAL2   5.0   PREDICT   Num   8.0    8.0  DOLLAR12.2      NaN  Predicted Sales
6   SASHELP.PRDSAL2   6.0  PRODTYPE  Char  10.0  100.0    $CHAR10.      NaN     Product Type
7   SASHELP.PRDSAL2   7.0   PRODUCT  Char  10.0  110.0    $CHAR10.      NaN          Product
8   SASHELP.PRDSAL2   9.0   QUARTER   Num   8.0   24.0          8.      NaN          Quarter
9   SASHELP.PRDSAL2   2.0     STATE  Char  22.0   58.0    $CHAR22.      NaN   State/Province
10  SASHELP.PRDSAL2   8.0      YEAR   Num   8.0   16.0          4.      NaN             YearThe SAS table PRDSAL2 from the SASHELP library has the following columns:

1. ACTUAL: This is a numeric column with a length of 8. It uses the DOLLAR12.2 format and represents the actual sales.
2. COUNTRY: This is a character column with a length of 10. It uses the $CHAR10. format and represents the country.
3. COUNTY: This is a character column with a length of 20. It uses the $CHAR20. format and represents the county.
4. MONTH: This is a numeric column with a length of 8. It uses the MONNAME3. format and represents the month.
5. MONYR: This is a numeric column with a length of 8. It uses the MONYY. format and represents the month/year.
6. PREDICT: This is a numeric column with a length of 8. It uses the DOLLAR12.2 format and represents the predicted sales.
7. PRODTYPE: This is a character column with a length of 10. It uses the $CHAR10. format and represents the product type.
8. PRODUCT: This is a character column with a length of 10. It uses the $CHAR10. format and represents the product.
9. QUARTER: This is a numeric column with a length of 8. It uses the 8. format and represents the quarter.
10. STATE: This is a character column with a length of 22. It uses the $CHAR22. format and represents the state/province.
11. YEAR: This is a numeric column with a length of 8. It uses the 4. format and represents the year.

> Finished chain.

I will ask to test memory:  Are there any columns containing date or period of time?
> Entering new AgentExecutor chain...
Yes, there are columns containing date or period of time in the PRDSAL2 table from the SASHELP library. These columns are:

1. MONTH: This is a numeric column with a length of 8. It uses the MONNAME3. format and represents the month.
2. MONYR: This is a numeric column with a length of 8. It uses the MONYY. format and represents the month/year.
3. QUARTER: This is a numeric column with a length of 8. It uses the 8. format and represents the quarter.
4. YEAR: This is a numeric column with a length of 8. It uses the 4. format and represents the year.

I will ask:  Append the table PRDSAL2 from SASHELP library to the table PRDSAL3 from SASHELP library
> Entering new AgentExecutor chain...
Invoking: `append_table` with `SASHELP.PRDSAL2, SASHELP.PRDSAL3`

SAS server started using Context SAS Studio compute context with SESSION_ID=8ecc570f-0f01-4153-9e32-59da3d37d7ab-ses0000
12   ods listing close;ods html5 (id=saspy_internal) options(bitmap_mode='inline') device=svg style=HTMLBlue; ods graphics on /
12 ! outputfmt=png;
NOTE: Writing HTML5(SASPY_INTERNAL) Body file: sashtml.htm
13
14   data sasdm.new; set SASHELP.PRDSAL2;run;

NOTE: There were 23040 observations read from the data set SASHELP.PRDSAL2.
NOTE: The data set SASDM.NEW has 23040 observations and 11 variables.
NOTE: DATA statement used (Total process time):
      real time           0.03 seconds
      user cpu time       0.00 seconds
      system cpu time     0.00 seconds
      memory              626.15k
      OS Memory           17764.00k
      Timestamp           01/23/2024 01:51:06 AM
      Step Count                        3  Switch Count  0
      Page Faults                       0
      Page Reclaims                     168
      Page Swaps                        0
      Voluntary Context Switches        76
      Involuntary Context Switches      0
      Block Input Operations            32
      Block Output Operations           5512


14 !                                          proc append base=sasdm.new data= SASHELP.PRDSAL3 force; run;

NOTE: Appending SASHELP.PRDSAL3 to SASDM.NEW.
WARNING: Variable DATE was not found on BASE file. The variable will not be added to the BASE file.
WARNING: Variable MONYR was not found on DATA file.
NOTE: FORCE is specified, so dropping/truncating will occur.
NOTE: There were 11520 observations read from the data set SASHELP.PRDSAL3.
NOTE: 11520 observations added.
NOTE: The data set SASDM.NEW has 34560 observations and 11 variables.
NOTE: PROCEDURE APPEND used (Total process time):
      real time           0.01 seconds
      user cpu time       0.01 seconds
      system cpu time     0.00 seconds
      memory              715.50k
      OS Memory           18020.00k
      Timestamp           01/23/2024 01:51:06 AM
      Step Count                        4  Switch Count  0
      Page Faults                       0
      Page Reclaims                     101
      Page Swaps                        0
      Voluntary Context Switches        48
      Involuntary Context Switches      0
      Block Input Operations            288
      Block Output Operations           2960

14 !                                                                                                       quit;

15   ods html5 (id=saspy_internal) close;ods listing;
16

The tables PRDSAL2 and PRDSAL3 from the SASHELP library have been successfully appended. The new table is stored in the SASDM library and is named "NEW". It contains 34560 observations and 11 variables.
Please note that the variable "DATE" was not found in the PRDSAL2 table and the variable "MONYR" was not found in the PRDSAL3 table.

> Finished chain.

I will ask to test memory:  How many rows again?
> Entering new AgentExecutor chain...
The new appended table contains 34560 rows.
> Finished chain.

I will ask:  Provide detailed table description for table NEW from SASDM library
> Entering new AgentExecutor chain...

Invoking: `get_table_information` with `SASDM.NEW`

SAS server started using Context SAS Studio compute context with SESSION_ID=7b7f0494-181a-496c-a2f3-35cb4605c742-ses0000
12   ods listing close;ods html5 (id=saspy_internal) options(bitmap_mode='inline') device=svg style=HTMLBlue; ods graphics on /
12 ! outputfmt=png;
NOTE: Writing HTML5(SASPY_INTERNAL) Body file: sashtml.htm
13
14   PROC CONTENTS DATA=SASDM.NEW;run;

NOTE: PROCEDURE CONTENTS used (Total process time):
      real time           0.03 seconds
      user cpu time       0.03 seconds
      system cpu time     0.00 seconds
      memory              1937.50k
      OS Memory           19300.00k
      Timestamp           01/23/2024 01:51:44 AM
      Step Count                        3  Switch Count  0
      Page Faults                       0
      Page Reclaims                     671
      Page Swaps                        0
      Voluntary Context Switches        3
      Involuntary Context Switches      3
      Block Input Operations            0
      Block Output Operations           8

14 !                                  quit;

15   ods html5 (id=saspy_internal) close;ods listing;
16

The table NEW from the SASDM library has the following details:

1. ACTUAL: This is a numeric column with a length of 8. It uses the DOLLAR12.2 format and represents the actual sales.
2. COUNTRY: This is a character column with a length of 10. It uses the $CHAR10. format and represents the country.
3. COUNTY: This is a character column with a length of 20. It uses the $CHAR20. format and represents the county.
4. MONTH: This is a numeric column with a length of 8. It uses the MONNAME3. format and represents the month.
5. MONYR: This is a numeric column with a length of 8. It uses the MONYY. format and represents the month/year.
6. PREDICT: This is a numeric column with a length of 8. It uses the DOLLAR12.2 format and represents the predicted sales.
7. PRODTYPE: This is a character column with a length of 10. It uses the $CHAR10. format and represents the product type.
8. PRODUCT: This is a character column with a length of 10. It uses the $CHAR10. format and represents the product.
9. QUARTER: This is a numeric column with a length of 8. It uses the 8. format and represents the quarter.
10. STATE: This is a character column with a length of 22. It uses the $CHAR22. format and represents the state/province.
11. YEAR: This is a numeric column with a length of 8. It uses the 4. format and represents the year.

The table has a total of 34560 observations.

> Finished chain.

I will ask to test memory:  In what library is stored that table?
> Entering new AgentExecutor chain...
The table "NEW" is stored in the SASDM library.
> Finished chain.
SAS server terminated

 

You can watch the video in GPT-4 Assisted Data Management in SAS Viya: A Custom LangChain Agent Approach to follow the execution logs.

 

Appending Tables

 

The program is able to append the table PRDSAL2 from the SASHELP library to the table PRDSAL3 from the SASHELP library. The operation is successful and the new table, named "NEW", is stored in the SASDM library. It has 34560 observations and 11 variables. **Invoking: append_table with SASHELP.PRDSAL2, SASHELP.PRDSAL3**

 

The tables PRDSAL2 and PRDSAL3 from the SASHELP library have been successfully appended. The new table is stored in the SASDM library and is named "NEW". It contains 34560 observations and 11 variables.
Please note that the variable "DATE" was not found in the PRDSAL2 table and the variable "MONYR" was not found in the PRDSAL3 table.

> Finished chain.

I will ask to test memory:  How many rows again?
> Entering new AgentExecutor chain...
The new appended table contains 34560 rows.
> Finished chain.

 

Conclusions

 

The implementation of a custom SAS Viya agent in LangChain is successful, demonstrating the potential of using LLMs and specific tools to create intelligent, interactive agents. The next steps could involve expanding the range of tools available to the agent and optimizing the agent’s memory component to handle more complex interactions.

 

Additional Resources

 

 

What To Read Next

 

Want to view a demonstration of this custom agent? View the video in GPT-4 Assisted Data Management in SAS Viya: A Custom LangChain Agent Approach

 

Thank you for your time reading this post. If you liked the post, give it a thumbs up! Please comment and tell us what you think about having conversations with your data. If you wish to get more information, please write me an email.

Version history
Last update:
‎02-09-2024 01:01 AM
Updated by:
Contributors

sas-innovate-2024.png

Don't miss out on SAS Innovate - Register now for the FREE Livestream!

Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.

 

Register now!

Free course: Data Literacy Essentials

Data Literacy is for all, even absolute beginners. Jump on board with this free e-learning  and boost your career prospects.

Get Started

Article Tags