Skip to content

Commit 464c4d9

Browse files
- Added multimodal support
- Addded new Anthropoc models - Included LLM function Sentiment Entity, Parse Doc, Classify Text - Fixed Cortex Search display issue - Improved chat interface
1 parent 9d628d0 commit 464c4d9

13 files changed

+549
-278
lines changed

README.md

Lines changed: 42 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,33 @@
11
# Snowflake AI Toolkit
2-
Snowflake AI Toolkit is an AI Accelerator and Playground for enabling AI in Snowflake. It is an Plug and Play Streamlit based Native App that can be used to explore, learn and build rapid prototypes of AI Solutions in Snowflake powered by the Snowflake's Cortex and AI Functions.
2+
3+
Snowflake AI Toolkit is an AI Accelerator and Playground for enabling AI in Snowflake. It is an Plug and Play Streamlit based Native App that can be used to explore, learn and build rapid prototypes of AI Solutions in Snowflake powered by the Snowflake's Cortex and AI Functions.
34

45
# Features
56

67
### Playground
8+
79
An interactive environment where users can chat and experiment with Snowflake Cortex functions, test prompts, and and play around with cortex functions.
810

911
### Build
12+
1013
A dedicated section for constructing and deploying data pipelines and workflows using Snowflake Cortex's powerful AI capabilities, enabling seamless integration with your Snowflake databases and tables
14+
1115
- Text completion and generation using the COMPLETE function
1216
- Retrieval-Augmented Generation (RAG) for question answering with your own data
1317
- Fine-tuning large language models on your custom datasets
1418

1519
### Search
20+
1621
Get a hybrid (vector and keyword) search engine on your text data in minutes,
22+
1723
- Create and manage Cortex Search Service
1824
- Use Cortex Search for your RAG Application
1925
- Use Cortex Search Powered Chat
2026

2127
### Agent
28+
2229
Cortex Agents orchestrate across both structured and unstructured data sources to deliver insights.
30+
2331
- Create and Manage Cortex Agent Instances
2432
- Test the Agent against the Data
2533
- Utilize Cortex Search and Cortex Analyst through Agents
@@ -37,32 +45,37 @@ Before you begin, ensure you have met the following requirements:
3745
- **Python**: Version 3.7 or higher.
3846
- **Streamlit**: Installed on your local machine.
3947
- **Snowflake-CLI** : Install snowflake-cli through pip
48+
- **Model Availability**: `claude-4-sonnet` and `claude-4-opus` is available only in AWS US (cross-region).
4049

4150
## Installation
4251

4352
1. Clone the repository:
53+
4454
```bash
4555
git clone https://github.com/sgsshankar/Snowflake-AI-Toolkit.git
4656
cd snowflake-ai-toolkit
4757
```
4858

4959
2. Install dependencies (only required for local development):
60+
5061
```bash
5162
pip install -r requirements.txt
5263
```
53-
64+
5465
All necessary libraries are listed in `requirements.txt`.
5566

5667
## Setup
5768

5869
The application will automatically handle:
70+
5971
- Database creation
6072
- Stage setup
6173
- Required resource initialization
6274

6375
Make sure your Snowflake role has the necessary privileges for these operations.
6476

6577
To configure the application mode, update the `mode` parameter in `src/settings_config.json`:
78+
6679
- Set to `"debug"` for local development and editing.
6780
- Set to `"native"` for running natively in Snowflake.
6881

@@ -96,7 +109,7 @@ Use the fingerprint in `rsa_public_key_fp`.
96109

97110
#### Step 3: Add to `settings_config.json`
98111

99-
- Paste full contents of `rsa_private_key.p8` into `rsa_private_key` (escape newlines if needed).
112+
- Paste full contents of `rsa_private_key.p8` into `rsa_private_key` (add \n).
100113
- Paste fingerprint into `rsa_public_key_fp`.
101114

102115
For more details, refer to the [Snowflake documentation](https://docs.snowflake.com/en/user-guide/key-pair-auth.html#using-key-pair-authentication).
@@ -106,47 +119,50 @@ For more details, refer to the [Snowflake documentation](https://docs.snowflake.
106119
### Locally
107120

108121
Launch the application locally using:
109-
```bash
110-
streamlit run streamlit_app.py
111-
```
122+
123+
```bash
124+
streamlit run streamlit_app.py
125+
```
112126

113127
### Natively on Snowflake
114128

115129
To deploy the application natively in Snowflake, use the following command:
116-
```bash
117-
snow streamlit deploy --account "<your_account>" --user "<your_username>" --password "<your_password>" --role "<your_role>" --warehouse "<your_warehouse>" --database "<your_database>" --replace
118-
```
130+
131+
```bash
132+
snow streamlit deploy --account "<your_account>" --user "<your_username>" --password "<your_password>" --role "<your_role>" --warehouse "<your_warehouse>" --database "<your_database>" --replace
133+
```
119134

120135
Replace the placeholders (`<your_account>`, `<your_username>`, etc.) with your actual Snowflake account details. When running natively in Snowflake, installing dependencies from `requirements.txt` is not needed.
121136

122137
## Project Structure
123138

124-
| File/Directory | Description |
125-
|-------------------------------------|--------------------------------------------------|
126-
| [src/](src/) | Source code for setup and styling |
127-
| [src/setup.py](src/setup.py) | Setup and initialization code |
128-
| [src/styles.css](src/styles.css) | Custom styling |
129-
| [src/build.py](src/build.py) | Build mode functionality |
130-
| [src/cortex_functions.py](src/cortex_functions.py) | Core functions for Cortex operations |
131-
| [src/query_result_builder.py](src/query_result_builder.py) | Query result handling and display |
132-
| [src/playground.py](src/playground.py) | Playground mode functionality |
133-
| [src/rag.py](src/rag.py) | RAG mode functionality |
134-
| [src/fine_tune.py](src/fine_tune.py) | Fine-tuning functionality |
135-
| [src/search.py](src/search.py) | Cortex Search Functionality |
136-
| [.gitignore](.gitignore) | Git ignore file |
137-
| [requirements.txt](requirements.txt)| Project dependencies |
138-
| [streamlit_app.py](streamlit_app.py)| Main application entry point |
139-
139+
| File/Directory | Description |
140+
| ---------------------------------------------------------- | ------------------------------------ |
141+
| [src/](src/) | Source code for setup and styling |
142+
| [src/setup.py](src/setup.py) | Setup and initialization code |
143+
| [src/styles.css](src/styles.css) | Custom styling |
144+
| [src/build.py](src/build.py) | Build mode functionality |
145+
| [src/cortex_functions.py](src/cortex_functions.py) | Core functions for Cortex operations |
146+
| [src/query_result_builder.py](src/query_result_builder.py) | Query result handling and display |
147+
| [src/playground.py](src/playground.py) | Playground mode functionality |
148+
| [src/rag.py](src/rag.py) | RAG mode functionality |
149+
| [src/fine_tune.py](src/fine_tune.py) | Fine-tuning functionality |
150+
| [src/search.py](src/search.py) | Cortex Search Functionality |
151+
| [.gitignore](.gitignore) | Git ignore file |
152+
| [requirements.txt](requirements.txt) | Project dependencies |
153+
| [streamlit_app.py](streamlit_app.py) | Main application entry point |
140154

141155
## Troubleshooting
142156

143157
Common issues and solutions:
144158

145159
1. **Snowflake Permission Errors**
160+
146161
- Verify role privileges for database and stage creation
147162
- Ensure Cortex functionalities are enabled
148163

149164
2. **Dependency Issues**
165+
150166
- If pandas/pyarrow installation fails:
151167
```bash
152168
pip install pandas pyarrow
@@ -168,11 +184,11 @@ We welcome contributions! Please:
168184
## Support
169185

170186
For assistance:
187+
171188
- Open an issue in the GitHub repository
172189
- Contact project maintainers
173190
- Check documentation for common solutions
174191

175-
176192
## Warranty
177193

178194
The Software is provided as Open Source. This software is provided “as is” and any express or implied warranties, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed. In no event shall the owner or contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

src/build.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -143,15 +143,15 @@ def get_non_playground_input(session, functionality):
143143

144144
# Database and schema selections at the same level
145145
col1, col2 = st.columns(2)
146-
database = col1.selectbox("Select Database", list_databases(session))
147-
schema = col2.selectbox("Select Schema", list_schemas(session, database) if database else [], disabled=not database)
146+
database = col1.selectbox("Database", list_databases(session))
147+
schema = col2.selectbox("Schema", list_schemas(session, database) if database else [], disabled=not database)
148148

149149
# Table and column selections at the same level
150150
col3, col4 = st.columns(2)
151151
tables = list_tables(session, database, schema) if schema else []
152-
selected_table = col3.selectbox("Select Table", tables if tables else ["No tables available"], disabled=not schema)
152+
selected_table = col3.selectbox("Table", tables if tables else ["No tables available"], disabled=not schema)
153153
columns = list_columns(session, database, schema, selected_table) if selected_table != "No tables available" else []
154-
selected_column = col4.selectbox("Select Column", columns if columns else ["No columns available"], disabled=not selected_table or selected_table == "No tables available")
154+
selected_column = col4.selectbox("Column", columns if columns else ["No columns available"], disabled=not selected_table or selected_table == "No tables available")
155155

156156
if selected_table != "No tables available" and selected_column != "No columns available":
157157
st.write(f"Preview of `{selected_table}`")
@@ -166,7 +166,7 @@ def get_non_playground_input(session, functionality):
166166
st.subheader("Select Output Table and Column")
167167

168168
col5, col6 = st.columns(2)
169-
output_table = col5.text_input("Enter New Output Table Name", placeholder="New output table")
169+
output_table = col5.text_input("New Output Table Name", placeholder="New output table")
170170
output_column = col6.text_input("Output Column Name", placeholder="Enter output column name")
171171

172172
input_data = {
@@ -197,7 +197,7 @@ def display_build(session):
197197

198198
# Extend the functionality options to include RAG and Fine Tune
199199
functionality = st.selectbox(
200-
"Choose functionality:", ["Select Functionality", "Complete", "Translate", "Summarize", "Extract", "Sentiment", "RAG", "Fine Tune"]
200+
"Choose functionality:", ["Complete", "Translate", "Summarize", "Extract", "Sentiment", "RAG", "Fine Tune"]
201201
)
202202

203203
if functionality != "Select Functionality":
@@ -211,7 +211,7 @@ def display_build(session):
211211
settings = get_functionality_settings(functionality, config,session)
212212
input_data = get_non_playground_input(session, functionality)
213213

214-
if st.button(f"Run {functionality}"):
214+
if st.button(f"Run"):
215215
try:
216216
trigger_async_operation(session, functionality, input_data, settings)
217217
st.success(f"Operation {functionality} triggered. Check the notifications screen for updates.")

src/cortex_agent.py

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
"model": "", # AI model to use
2727
"tools": [], # List of tool specifications
2828
"tool_resources": {}, # Configuration for each tool
29-
"response_instruction": "You will always maintain a friendly tone and provide concise response. When a user asks you a question, you will also be given excerpts from different sources provided by a search engine. Use that information to provide a summary that addresses the user's question. Question: {{.Question}}\n\nContext: {{.Context}}",
29+
"response_instruction": "You will always maintain a friendly tone and provide concise response. When a user asks you a question, you will also be given excerpts from different sources provided by a search engine.",
3030
}
3131

3232
def run_snowflake_query(session, query):
@@ -106,6 +106,7 @@ def _generate_jwt_token(self, rsa_public_key_fp):
106106
# print("token: ", token)
107107
return token, expiration
108108
except Exception as e:
109+
print(e)
109110
st.error(f"Error generating JWT token: {str(e)}")
110111
return None, None
111112

@@ -627,18 +628,18 @@ def update_tool_resources(tool_name, tool_type, tool_resources, i):
627628

628629
st.divider()
629630

630-
if st.button(f"Add", key=f"{prefix.lower()}add_tool"):
631-
new_tool_name = f"tool_{len(tools_list) + 1}"
632-
tools_list.append({"tool_spec": {"type": "cortex_search", "name": new_tool_name}})
633-
st.rerun()
634-
635631
# Response instruction input
636632
filled_settings["response_instruction"] = st.text_area(
637633
f"Response Instruction",
638634
value=prefilled_values["response_instruction"],
639635
key=f"{prefix.lower()}response_instruction"
640636
)
641637

638+
if st.button(f"Add", key=f"{prefix.lower()}add_tool"):
639+
new_tool_name = f"tool_{len(tools_list) + 1}"
640+
tools_list.append({"tool_spec": {"type": "cortex_search", "name": new_tool_name}})
641+
st.rerun()
642+
642643
# Update settings with tools data
643644
filled_settings["tools"] = tools_list
644645
filled_settings["tool_resources"] = tool_resources
@@ -656,9 +657,9 @@ def display_cortex_agent(session):
656657
st.title("Cortex Agent")
657658
agent_manager = CortexAgentManager(session)
658659

659-
tab1, tab2, tab3 = st.tabs(["Create", "Edit", "Use"])
660+
option = st.selectbox("Choose Functionality", ["Create", "Edit"], key="agent_option")
660661

661-
with tab1:
662+
if option == "Create":
662663
# Create Agent Tab
663664
st.subheader("Create Agent")
664665
col1, col2 = st.columns(2)
@@ -674,10 +675,11 @@ def display_cortex_agent(session):
674675
new_settings = render_dynamic_settings_form(session, SETTINGS_TEMPLATE, prefix="Create")
675676
new_settings["model"] = model
676677

677-
if st.button("Create Agent", key="create_agent"):
678+
if st.button("Create", key="create_agent"):
678679
if name.strip():
679680
new_agent = CortexAgent(name=name, settings=new_settings)
680-
response_instruction = new_settings.get("response_instruction", "")
681+
new_settings["response_instruction"] = new_settings.get("response_instruction", "") + "Use that information to provide a summary that addresses the user's question. Question: {{.Question}}\n\nContext: {{.Context}}"
682+
response_instruction = new_settings.get("response_instruction", "")
681683
if "{{.Question}}" not in response_instruction or "{{.Context}}" not in response_instruction:
682684
show_toast_message("Response instruction must include {{.Question}} and {{.Context}}", toast_type="error")
683685
return
@@ -693,7 +695,7 @@ def display_cortex_agent(session):
693695
else:
694696
st.error("Agent name cannot be empty")
695697

696-
with tab2:
698+
elif option == "Edit":
697699
# Edit Agent Tab
698700
st.subheader("Edit Existing Agent")
699701
agents = agent_manager.get_all_agents()
@@ -728,7 +730,7 @@ def display_cortex_agent(session):
728730

729731
# print("settings: " , json.dumps(updated_settings, indent=2))
730732

731-
if st.button("Update Agent", key="edit_button"):
733+
if st.button("Update", key="edit_button"):
732734
if new_name.strip():
733735
updated_agent = agent.edit(session, new_name, updated_settings)
734736
if agent_manager.save_agent(updated_agent):
@@ -742,7 +744,7 @@ def display_cortex_agent(session):
742744
else:
743745
st.error("Agent name and RSA public key fingerprint cannot be empty")
744746

745-
with tab3:
747+
else:
746748
# Chat Tab
747749
st.subheader("Use Agent")
748750
agents = agent_manager.get_all_agents()
@@ -765,9 +767,13 @@ def display_cortex_agent(session):
765767
st.markdown("### Generated SQL")
766768
st.code(sql, language="sql")
767769
sql_result = run_snowflake_query(session, sql)
770+
# explanations = make_llm_call(session,"Explain the SQL Query", str(sql), "claude-3-5-sonnet")
771+
# st.write("### SQL Query Explanation")
772+
# st.markdown(explanations)
768773
if sql_result is not None:
769774
st.write("### Query Results")
770775
st.dataframe(sql_result)
776+
771777
else:
772778
st.error("Error executing SQL query")
773779
else:

0 commit comments

Comments
 (0)