Skip to content
This repository was archived by the owner on Dec 1, 2025. It is now read-only.

Commit c989881

Browse files
committed
make chat context specific. create multi-context dir
1 parent 3b3d078 commit c989881

6 files changed

Lines changed: 62 additions & 30 deletions

File tree

README.md

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,10 @@ Data Neuron is a powerful AI-driven data framework to create and maintain AI DAT
44

55
Supports SQLite, PostgreSQL, MySQL, MSSQL, CSV files(through duckdb). Works with major LLMs like Claude (default), OpenAI, LLAMA etc(through groq, nvidia, ..), OLLAMA.
66

7-
87
https://github.com/user-attachments/assets/2301e7cd-a895-4b9b-8a8f-2f30c3e02e16
98

10-
119
https://github.com/user-attachments/assets/5f6ed1f2-58cd-4e75-ae0b-745f7177a746
1210

13-
14-
1511
### The framework:
1612

1713
<img width="621" alt="Screenshot 2024-07-25 at 11 30 35 PM" src="https://github.com/user-attachments/assets/09353e34-a0f7-4650-b477-746eaf10c354">
@@ -102,15 +98,24 @@ pip install "dataneuron[mysql]"
10298
dnn --init
10399
```
104100

105-
This will create YAML files in the `context/` directory which will be your semantic layer for your data.
101+
This will prompt for a context name, you can give `product_analytics` or `customer_success` or any and it will then create YAML files in the `context/<contextname>` directory which will be your semantic layer for your data.
106102
You will be told to select couple of tables, so that it can be auto-labelled which you can edit later.
107103

108104
3. Or start an interactive chat session:
109105

110106
```
111-
dnn --chat
107+
dnn --chat <context_name>
112108
```
113109

110+
eg:
111+
112+
```
113+
dnn --chat product_analytics
114+
```
115+
116+
You can chat with the semantic layer that you have created. And you will also be able to save the metric
117+
to a dashboard, this will get created under `dashboards/<dashname>.yml`
118+
114119
4. You can generate reports with image as input for your dashboards. You need to have `wkhtmltopdf` in your system.
115120
For mac
116121

src/data_neuron/chat_cmd/main.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,23 @@ def list_dashboards():
3434
return [f.split('.')[0] for f in os.listdir(dashboards_dir) if f.endswith('.yml')]
3535

3636

37-
def start_chat():
37+
def start_chat(context_name=None):
3838
print_header("Starting DATA neuron chat session...")
3939
print_warning(
40-
"Please remember your messages and result wll be sent to LLM for API call.")
41-
print_info("🗄️ Fetching the context from your context folder\n")
42-
context = load_context()
40+
"Please remember your messages and result will be sent to LLM for API call.")
41+
42+
if context_name is None:
43+
context_name = styled_prompt(
44+
"Please enter the name of the context you want to use")
45+
46+
context_dir = os.path.join('context', context_name)
47+
if not os.path.exists(context_dir):
48+
print_warning(
49+
f"Context '{context_name}' does not exist. Please create it using 'dnn --init' first.")
50+
return
51+
52+
print_info(f"🗄️ Fetching the context from {context_dir}\n")
53+
context = load_context(context_name)
4354
print_success("Context is loaded!\n")
4455

4556
chat_history = []
@@ -83,7 +94,7 @@ def process_with_llm(query: str, context: dict, chat_history: list):
8394
print_header("DATA neuron is thinking...")
8495
print_prompt("🤖 Sending request to LLM\n")
8596
print_info("Rephrasing the question suited for db")
86-
changed_query = process_query(query)
97+
changed_query = process_query(query, context)
8798
prompt = sql_query_prompt(changed_query, context)
8899
system_prompt = "You are a helpful assistant that generates SQL queries based on natural language questions and maintains context throughout the conversation."
89100

src/data_neuron/cli.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
# @click.option('--ask', help='The question you want to ask about the database.')
1515
@click.option('--db-init', type=click.Choice(['sqlite', 'mysql', 'mssql', 'postgres', 'csv', 'clickhouse']), help='Initialize database configuration.')
1616
# New option for chat
17-
@click.option('--chat', is_flag=True, help='Start an interactive chat session.')
17+
@click.option('--chat', help='Start an interactive chat session.', type=str)
1818
@click.option('--version', is_flag=True, help='Show the version of the tool')
1919
# New option
2020
@click.option('--report', is_flag=True, help='Generate a dashboard report.')
@@ -26,7 +26,7 @@ def cli(init, db_init, chat, version, report):
2626
elif db_init:
2727
init_database_config(db_init)
2828
elif chat:
29-
start_chat() # New function call for chat functionality
29+
start_chat(chat) # New function call for chat functionality
3030
elif version:
3131
click.echo(f"Data Neuron CLI version {VERSION}")
3232
return

src/data_neuron/context_init_cmd/main.py

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import os
2+
import click
23
from .table_operations import get_table_list, choose_tables, generate_yaml_for_table
34
from .yaml_generator import generate_definitions_and_relationships
45
from ..utils.print import print_header, print_info, print_success, print_warning, print_prompt
@@ -7,18 +8,29 @@
78

89
@handle_database_errors
910
def init_context():
10-
print_header("Setting up the context(semantic layer) for your database..")
11+
print_header(
12+
"Setting up a new context(semantic layer) for your database..")
13+
14+
context_name = click.prompt(
15+
"Please enter a name for this context eg: customer_success or product_analytics", type=str)
16+
context_dir = os.path.join('context', context_name)
17+
18+
if os.path.exists(context_dir):
19+
overwrite = click.confirm(
20+
f"Context '{context_name}' already exists. Do you want to overwrite it?", default=False)
21+
if not overwrite:
22+
print_info("Context initialization cancelled.")
23+
return
24+
1125
print_warning(
12-
"This will create a folder context in the current directory. And override if there is an existing file")
26+
f"This will create a folder {context_dir} in the current directory. Existing files will be overwritten.")
1327
print_prompt("You can edit it anytime...")
1428
print_warning("Please choose a set of 10 or lesser tables..\n")
1529
print_info("🗄️ Fetching tables from the database")
16-
1730
db_type, all_tables = get_table_list()
18-
1931
chosen_tables = choose_tables(all_tables)
2032

21-
os.makedirs('context/tables', exist_ok=True)
33+
os.makedirs(os.path.join(context_dir, 'tables'), exist_ok=True)
2234

2335
for table_info in chosen_tables:
2436
if isinstance(table_info, dict):
@@ -29,8 +41,10 @@ def init_context():
2941
table = table_info
3042

3143
yaml_content = generate_yaml_for_table(schema, table)
32-
with open(f'context/tables/{schema}___{table}.yaml', 'w') as f:
44+
45+
with open(os.path.join(context_dir, 'tables', f'{schema}__{table}.yaml'), 'w') as f:
3346
f.write(yaml_content)
47+
3448
print("\n")
3549
print_success(f"Generated YAML for table: {schema}.{table}")
3650

@@ -39,15 +53,15 @@ def init_context():
3953
definitions_yaml, relationships_yaml = generate_definitions_and_relationships(
4054
chosen_tables, db_type)
4155

42-
with open('context/definitions.yaml', 'w') as f:
56+
with open(os.path.join(context_dir, 'definitions.yaml'), 'w') as f:
4357
f.write(definitions_yaml)
4458
print_success("Generated definitions.yaml")
4559

46-
with open('context/relationships.yaml', 'w') as f:
60+
with open(os.path.join(context_dir, 'relationships.yaml'), 'w') as f:
4761
f.write(relationships_yaml)
4862
print_success("Generated relationships.yaml")
4963

50-
print_success("Initialization complete!")
64+
print_success(f"Initialization complete for context: {context_name}")
5165
except Exception as e:
5266
print_warning(f"An error occurred: {str(e)}")
5367

src/data_neuron/context_loader.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,18 @@
55
CONFIG_PATH = 'database.yaml'
66

77

8-
def load_context():
8+
def load_context(context_name):
99
context = {
1010
'tables': {},
1111
'relationships': {},
1212
'global_definitions': {},
1313
'database': {}
1414
}
1515

16+
context_dir = os.path.join('context', context_name)
17+
1618
# Load table-specific context
17-
tables_path = os.path.join('context', 'tables')
19+
tables_path = os.path.join(context_dir, 'tables')
1820
for filename in os.listdir(tables_path):
1921
if filename.endswith('.yaml'):
2022
file_path = os.path.join(tables_path, filename)
@@ -33,13 +35,13 @@ def load_context():
3335
f"Warning: Invalid or empty YAML content in {filename}. Skipping this table.")
3436

3537
# Load relationships
36-
relationships_path = os.path.join('context', 'relationships.yaml')
38+
relationships_path = os.path.join(context_dir, 'relationships.yaml')
3739
if os.path.exists(relationships_path):
3840
with open(relationships_path, 'r') as f:
3941
context['relationships'] = yaml.safe_load(f)
4042

4143
# Load global definitions
42-
definitions_path = os.path.join('context', 'definitions.yaml')
44+
definitions_path = os.path.join(context_dir, 'definitions.yaml')
4345
if os.path.exists(definitions_path):
4446
with open(definitions_path, 'r') as f:
4547
context['global_definitions'] = yaml.safe_load(f)

src/data_neuron/query_refiner.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88

99

1010
class LLMQueryRefiner:
11-
def __init__(self):
12-
self.context = load_context()
11+
def __init__(self, context):
12+
self.context = context
1313
self.db = DatabaseFactory.get_database()
1414
self.db_helper = DatabaseHelper(
1515
self.context['database'], self.db)
@@ -142,8 +142,8 @@ def further_refine_query(self, query: str, refined_entities: List[Dict]) -> str:
142142
return query
143143

144144

145-
def process_query(user_query: str) -> str:
146-
refiner = LLMQueryRefiner()
145+
def process_query(user_query: str, context: Dict) -> str:
146+
refiner = LLMQueryRefiner(context)
147147
refined_query, changes, refined_entities, invalid_entities = refiner.refine_query(
148148
user_query)
149149

0 commit comments

Comments
 (0)