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.
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.
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
SASPY: Submit workloads to SAS Viya from Python.
GPT-4 Assisted Data Management in SAS Viya: A Custom LangChain Agent Approach.
Conversing with Data: Turning Queries into Conversations with SAS Viya, Azure OpenAI and LangChain.
Exploring LangChain and Azure OpenAI’s Ability to Write SQL and Join Tables To Answer Questions.
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.
... View more