Skip to content

Commit b8d05fa

Browse files
Merge branch 'sinaptik-ai:main' into template_improvements
2 parents 8ccec5c + 273cf1b commit b8d05fa

File tree

8 files changed

+60
-25
lines changed

8 files changed

+60
-25
lines changed

docs/v3/semantic-layer/views.mdx

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ description: "Learn how to work with views in PandasAI"
44
---
55

66
<Note title="Beta Notice">
7-
PandasAI 3.0 is currently in beta. This documentation reflects the latest features and functionality, which may evolve before the final release.
7+
PandasAI 3.0 is currently in beta. This documentation reflects the latest
8+
features and functionality, which may evolve before the final release.
89
</Note>
910

1011
## What are views?
@@ -68,21 +69,21 @@ view_relations = [
6869
# Select relevant columns for the sales analytics view
6970
view_columns = [
7071
# Order details
71-
"orders.id",
72-
"orders.order_date",
73-
"orders.total_amount",
74-
"orders.status",
75-
72+
{"name": "orders.id", "type": "integer"},
73+
{"name": "orders.order_date", "type": "date"},
74+
{"name": "orders.total_amount", "type": "float"},
75+
{"name": "orders.status", "type": "string"},
76+
7677
# Product information
77-
"products.name",
78-
"products.category",
79-
"products.unit_price",
80-
"products.stock_level",
81-
78+
{"name": "products.name", "type": "string"},
79+
{"name": "products.category", "type": "string"},
80+
{"name": "products.unit_price", "type": "float"},
81+
{"name": "products.stock_level", "type": "integer"},
82+
8283
# Customer information
83-
"customers.segment",
84-
"customers.country",
85-
"customers.join_date"
84+
{"name": "customers.segment", "type": "string"},
85+
{"name": "customers.country", "type": "string"},
86+
{"name": "customers.join_date", "type": "date"},
8687
]
8788

8889
# Create a comprehensive sales analytics view
@@ -125,16 +126,19 @@ relations:
125126
#### Constraints
126127
127128
1. **Mutual Exclusivity**:
129+
128130
- A schema cannot define both `table` and `view` simultaneously.
129131
- If `view` is `true`, then the schema represents a view.
130132

131133
2. **Column Format**:
134+
132135
- For views:
133136
- All columns must follow the format `[table].[column]`.
134137
- `from` and `to` fields in `relations` must follow the `[table].[column]` format.
135138
- Example: `loans.payment_amount`, `heart.condition`.
136139

137140
3. **Relationships for Views**:
141+
138142
- Each table referenced in `columns` must have at least one relationship defined in `relations`.
139143
- Relationships must specify `from` and `to` attributes in the `[table].[column]` format.
140144
- Relations define how different tables in your view are connected.

extensions/llms/litellm/pandasai_litellm/litellm.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def type(self) -> str:
4848
str: The type of the model."""
4949
return f"litellm"
5050

51-
def call(self, instruction: BasePrompt, _: AgentState = None) -> str:
51+
def call(self, instruction: BasePrompt, context: AgentState = None) -> str:
5252
"""Generates a completion response based on the provided instruction.
5353
5454
This method converts the given instruction into a user prompt string and
@@ -57,17 +57,18 @@ def call(self, instruction: BasePrompt, _: AgentState = None) -> str:
5757
5858
Args:
5959
instruction (BasePrompt): The instruction to convert into a prompt.
60-
_ (AgentState, optional): An optional state of the agent. Defaults to None.
60+
context (AgentState, optional): An optional state of the agent. Defaults to None.
6161
6262
Returns:
6363
str: The content of the model's response to the user prompt."""
6464

65-
user_prompt = instruction.to_string()
65+
memory = context.memory if context else None
66+
self.last_prompt = self.prepend_system_prompt(instruction.to_string(), memory)
6667

6768
return (
6869
completion(
6970
model=self.model,
70-
messages=[{"content": user_prompt, "role": "user"}],
71+
messages=[{"content": self.last_prompt, "role": "user"}],
7172
**self.params,
7273
)
7374
.choices[0]

extensions/llms/openai/pandasai_openai/base.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ def completion(self, prompt: str, memory: Memory) -> str:
115115
116116
Args:
117117
prompt (str): A string representation of the prompt.
118+
memory (Memory): Memory object containing conversation history.
118119
119120
Returns:
120121
str: LLM response.
@@ -139,6 +140,7 @@ def chat_completion(self, value: str, memory: Memory) -> str:
139140
140141
Args:
141142
value (str): Prompt
143+
memory (Memory): Memory object containing conversation history.
142144
143145
Returns:
144146
str: LLM response.

pandasai/agent/base.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ def _process_query(self, query: str, output_type: Optional[str] = None):
270270
self._state.assign_prompt_id()
271271

272272
# Generate code
273-
code = self.generate_code_with_retries(query)
273+
code = self.generate_code_with_retries(str(query))
274274

275275
# Execute code with retries
276276
result = self.execute_with_retries(code)
@@ -296,7 +296,7 @@ def _regenerate_code_after_error(self, code: str, error: Exception) -> str:
296296

297297
return self._code_generator.generate_code(prompt)
298298

299-
def _handle_exception(self, code: str) -> str:
299+
def _handle_exception(self, code: str) -> ErrorResponse:
300300
"""Handle exceptions and return an error message."""
301301
error_message = traceback.format_exc()
302302
self._state.logger.log(f"Processing failed with error: {error_message}")

pandasai/core/code_generation/base.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ def generate_code(self, prompt: BasePrompt) -> str:
1818
Generates code using a given LLM and performs validation and cleaning steps.
1919
2020
Args:
21-
context (PipelineContext): The pipeline context containing dataframes and logger.
2221
prompt (BasePrompt): The prompt to guide code generation.
2322
2423
Returns:
@@ -32,10 +31,16 @@ def generate_code(self, prompt: BasePrompt) -> str:
3231

3332
# Generate the code
3433
code = self._context.config.llm.generate_code(prompt, self._context)
34+
# Store the original generated code (for logging purposes)
3535
self._context.last_code_generated = code
3636
self._context.logger.log(f"Code Generated:\n{code}")
3737

38-
return self.validate_and_clean_code(code)
38+
# Validate and clean the code
39+
cleaned_code = self.validate_and_clean_code(code)
40+
# Update with the final cleaned code (for subsequent processing and multi-turn conversations)
41+
self._context.last_code_generated = cleaned_code
42+
43+
return cleaned_code
3944

4045
except Exception as e:
4146
error_message = f"An error occurred during code generation: {e}"

pandasai/core/prompts/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
def get_chat_prompt_for_sql(context: AgentState) -> BasePrompt:
2020
return GeneratePythonCodeWithSQLPrompt(
2121
context=context,
22-
last_code_generated=context.get("last_code_generated"),
22+
last_code_generated=context.last_code_generated,
2323
output_type=context.output_type,
2424
)
2525

pandasai/llm/base.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,11 +119,11 @@ def _extract_code(self, response: str, separator: str = "```") -> str:
119119

120120
return code
121121

122-
def prepend_system_prompt(self, prompt: BasePrompt, memory: Memory):
122+
def prepend_system_prompt(self, prompt: str, memory: Memory) -> str | Any:
123123
"""
124124
Append system prompt to the chat prompt, useful when model doesn't have messages for chat history
125125
Args:
126-
prompt (BasePrompt): prompt for chat method
126+
prompt (str): prompt for chat method
127127
memory (Memory): user conversation history
128128
"""
129129
return self.get_system_prompt(memory) + prompt if memory else prompt
@@ -164,6 +164,7 @@ def generate_code(self, instruction: BasePrompt, context: AgentState) -> str:
164164
165165
Args:
166166
instruction (BasePrompt): Prompt with instruction for LLM.
167+
context (AgentState): Context to pass.
167168
168169
Returns:
169170
str: A string of Python code.

tests/unit_tests/agent/test_agent.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,3 +542,25 @@ def test_handle_exception(self, agent):
542542
# Verify the error was logged
543543
mock_logger.log.assert_called_once()
544544
assert "Processing failed with error" in mock_logger.log.call_args[0][0]
545+
546+
def test_last_code_generated_retrieval(self, agent: Agent):
547+
"""Test that last_code_generated is correctly retrieved in get_chat_prompt_for_sql."""
548+
# Set last_code_generated
549+
test_code = "print('Test code')"
550+
agent._state.last_code_generated = test_code
551+
552+
# 使用 get_chat_prompt_for_sql 获取提示
553+
from pandasai.core.prompts import get_chat_prompt_for_sql
554+
555+
prompt = get_chat_prompt_for_sql(agent._state)
556+
557+
# 验证提示中使用了正确的 last_code_generated
558+
assert prompt.props["last_code_generated"] == test_code
559+
560+
# 验证不是从 intermediate_values 中获取的
561+
agent._state.add("last_code_generated", "Wrong code")
562+
prompt = get_chat_prompt_for_sql(agent._state)
563+
564+
# 应该仍然使用 last_code_generated 属性,而不是 intermediate_values 中的值
565+
assert prompt.props["last_code_generated"] == test_code
566+
assert prompt.props["last_code_generated"] != "Wrong code"

0 commit comments

Comments
 (0)