langchain-timbr 2.1.11__tar.gz → 2.1.13__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/.github/workflows/install-dependencies-and-run-tests.yml +3 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/PKG-INFO +1 -1
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/src/langchain_timbr/_version.py +2 -2
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/src/langchain_timbr/langgraph/execute_timbr_query_node.py +1 -1
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/src/langchain_timbr/langgraph/generate_timbr_sql_node.py +1 -1
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/src/langchain_timbr/langgraph/identify_concept_node.py +1 -1
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/src/langchain_timbr/utils/timbr_llm_utils.py +56 -31
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/src/langchain_timbr/utils/timbr_utils.py +17 -5
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/tests/conftest.py +2 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/tests/integration/test_langchain_chains.py +14 -1
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/tests/integration/test_langgraph_nodes.py +22 -1
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/.github/dependabot.yml +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/.github/pull_request_template.md +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/.github/workflows/_codespell.yml +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/.github/workflows/_fossa.yml +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/.github/workflows/publish.yml +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/.gitignore +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/LICENSE +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/README.md +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/SECURITY.md +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/pyproject.toml +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/pytest.ini +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/requirements.txt +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/requirements310.txt +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/requirements311.txt +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/src/langchain_timbr/__init__.py +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/src/langchain_timbr/config.py +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/src/langchain_timbr/langchain/__init__.py +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/src/langchain_timbr/langchain/execute_timbr_query_chain.py +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/src/langchain_timbr/langchain/generate_answer_chain.py +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/src/langchain_timbr/langchain/generate_timbr_sql_chain.py +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/src/langchain_timbr/langchain/identify_concept_chain.py +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/src/langchain_timbr/langchain/timbr_sql_agent.py +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/src/langchain_timbr/langchain/validate_timbr_sql_chain.py +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/src/langchain_timbr/langgraph/__init__.py +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/src/langchain_timbr/langgraph/generate_response_node.py +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/src/langchain_timbr/langgraph/validate_timbr_query_node.py +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/src/langchain_timbr/llm_wrapper/llm_wrapper.py +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/src/langchain_timbr/llm_wrapper/timbr_llm_wrapper.py +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/src/langchain_timbr/timbr_llm_connector.py +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/src/langchain_timbr/utils/general.py +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/src/langchain_timbr/utils/prompt_service.py +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/src/langchain_timbr/utils/temperature_supported_models.json +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/tests/README.md +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/tests/integration/test_agent_integration.py +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/tests/integration/test_azure_databricks_provider.py +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/tests/integration/test_azure_openai_model.py +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/tests/integration/test_chain_pipeline.py +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/tests/integration/test_chain_reasoning.py +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/tests/integration/test_jwt_token.py +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/tests/integration/test_timeout_functionality.py +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/tests/standard/conftest.py +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/tests/standard/test_chain_documentation.py +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/tests/standard/test_connection_validation.py +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/tests/standard/test_llm_wrapper_optional_params.py +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/tests/standard/test_optional_llm_integration.py +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/tests/standard/test_standard_chain_requirements.py +0 -0
- {langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/tests/standard/test_unit_tests.py +0 -0
|
@@ -9,6 +9,8 @@ on:
|
|
|
9
9
|
env:
|
|
10
10
|
TIMBR_URL: ${{ secrets.TIMBR_URL }}
|
|
11
11
|
TIMBR_TOKEN: ${{ secrets.TIMBR_TOKEN }}
|
|
12
|
+
TIMBR_ONTOLOGY_NO_DTIMBR_PERMS: ${{ secrets.TIMBR_ONTOLOGY_NO_DTIMBR_PERMS }}
|
|
13
|
+
TIMBR_TOKEN_NO_DTIMBR_PERMS: ${{ secrets.TIMBR_TOKEN_NO_DTIMBR_PERMS }}
|
|
12
14
|
LLM_TYPE: ${{ secrets.LLM_TYPE }}
|
|
13
15
|
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
|
14
16
|
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
|
@@ -20,6 +22,7 @@ env:
|
|
|
20
22
|
JWT_PASSWORD: ${{ secrets.JWT_PASSWORD }}
|
|
21
23
|
JWT_SCOPE: ${{ secrets.JWT_SCOPE }}
|
|
22
24
|
JWT_SECRET: ${{ secrets.JWT_SECRET }}
|
|
25
|
+
LLM_TIMEOUT: ${{ secrets.LLM_TIMEOUT }}
|
|
23
26
|
|
|
24
27
|
jobs:
|
|
25
28
|
test-python-310:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: langchain-timbr
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.13
|
|
4
4
|
Summary: LangChain & LangGraph extensions that parse LLM prompts into Timbr semantic SQL and execute them.
|
|
5
5
|
Project-URL: Homepage, https://github.com/WPSemantix/langchain-timbr
|
|
6
6
|
Project-URL: Documentation, https://docs.timbr.ai/doc/docs/integration/langchain-sdk/
|
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '2.1.
|
|
32
|
-
__version_tuple__ = version_tuple = (2, 1,
|
|
31
|
+
__version__ = version = '2.1.13'
|
|
32
|
+
__version_tuple__ = version_tuple = (2, 1, 13)
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
|
@@ -102,7 +102,7 @@ class ExecuteSemanticQueryNode:
|
|
|
102
102
|
|
|
103
103
|
def run(self, state: StateGraph) -> dict:
|
|
104
104
|
try:
|
|
105
|
-
prompt = state.messages[-1].content if state.messages[-1] else None
|
|
105
|
+
prompt = state.messages[-1].get('content') if state.messages[-1] and 'content' in state.messages[-1] else None
|
|
106
106
|
except Exception:
|
|
107
107
|
prompt = state.get('prompt', None)
|
|
108
108
|
|
|
@@ -94,7 +94,7 @@ class GenerateTimbrSqlNode:
|
|
|
94
94
|
|
|
95
95
|
def run(self, state: StateGraph) -> dict:
|
|
96
96
|
try:
|
|
97
|
-
prompt = state.messages[-1].content if
|
|
97
|
+
prompt = state.messages[-1].get('content') if state.messages[-1] and 'content' in state.messages[-1] else None
|
|
98
98
|
except Exception:
|
|
99
99
|
prompt = state.get('prompt', None)
|
|
100
100
|
|
|
@@ -66,7 +66,7 @@ class IdentifyConceptNode:
|
|
|
66
66
|
|
|
67
67
|
def run(self, state: StateGraph) -> dict:
|
|
68
68
|
try:
|
|
69
|
-
prompt = state.messages[-1].content if state.messages[-1] else None
|
|
69
|
+
prompt = state.messages[-1].get('content') if state.messages[-1] and 'content' in state.messages[-1] else None
|
|
70
70
|
except Exception:
|
|
71
71
|
prompt = state.get('prompt', None)
|
|
72
72
|
|
{langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/src/langchain_timbr/utils/timbr_llm_utils.py
RENAMED
|
@@ -304,7 +304,7 @@ def determine_concept(
|
|
|
304
304
|
|
|
305
305
|
concepts_desc_arr.append(concept_verbose)
|
|
306
306
|
|
|
307
|
-
if len(concepts_and_views) == 1:
|
|
307
|
+
if len(concepts_and_views) == 1:
|
|
308
308
|
# If only one concept is provided, return it directly
|
|
309
309
|
determined_concept_name = list(concepts_and_views.keys())[0]
|
|
310
310
|
else:
|
|
@@ -763,42 +763,67 @@ def generate_sql(
|
|
|
763
763
|
if reasoning_status == "correct":
|
|
764
764
|
break
|
|
765
765
|
|
|
766
|
-
# Step 2: Regenerate SQL with feedback
|
|
766
|
+
# Step 2: Regenerate SQL with feedback (with validation retries)
|
|
767
767
|
evaluation_note = note + f"\n\nThe previously generated SQL: `{sql_query}` was assessed as '{evaluation.get('assessment')}' because: {evaluation.get('reasoning', '*could not determine cause*')}. Please provide a corrected SQL query that better answers the question: '{question}'."
|
|
768
768
|
|
|
769
769
|
# Increase graph depth for 2nd+ reasoning attempts, up to max of 3
|
|
770
770
|
context_graph_depth = min(3, int(graph_depth) + step) if graph_depth < 3 and step > 0 else graph_depth
|
|
771
|
-
regen_result = _generate_sql_with_llm(
|
|
772
|
-
question=question,
|
|
773
|
-
llm=llm,
|
|
774
|
-
conn_params=conn_params,
|
|
775
|
-
generate_sql_prompt=generate_sql_prompt,
|
|
776
|
-
current_context=_build_sql_generation_context(
|
|
777
|
-
conn_params=conn_params,
|
|
778
|
-
schema=schema,
|
|
779
|
-
concept=concept,
|
|
780
|
-
concept_metadata=concept_metadata,
|
|
781
|
-
graph_depth=context_graph_depth,
|
|
782
|
-
include_tags=include_tags,
|
|
783
|
-
exclude_properties=exclude_properties,
|
|
784
|
-
db_is_case_sensitive=db_is_case_sensitive,
|
|
785
|
-
max_limit=max_limit),
|
|
786
|
-
note=evaluation_note,
|
|
787
|
-
should_validate_sql=should_validate_sql,
|
|
788
|
-
timeout=timeout,
|
|
789
|
-
debug=debug,
|
|
790
|
-
)
|
|
791
771
|
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
772
|
+
# Regenerate SQL with validation retries
|
|
773
|
+
# Always validate during reasoning to ensure quality, regardless of global should_validate_sql flag
|
|
774
|
+
validation_iteration = 0
|
|
775
|
+
regen_is_valid = False
|
|
776
|
+
regen_error = ''
|
|
777
|
+
regen_sql = None
|
|
778
|
+
|
|
779
|
+
while validation_iteration < retries and (regen_sql is None or not regen_is_valid):
|
|
780
|
+
validation_iteration += 1
|
|
781
|
+
validation_err_txt = f"\nThe regenerated SQL (`{regen_sql}`) was invalid with error: {regen_error}. Please generate a corrected query." if regen_error and "snowflake" not in llm._llm_type else ""
|
|
782
|
+
|
|
783
|
+
regen_result = _generate_sql_with_llm(
|
|
784
|
+
question=question,
|
|
785
|
+
llm=llm,
|
|
786
|
+
conn_params=conn_params,
|
|
787
|
+
generate_sql_prompt=generate_sql_prompt,
|
|
788
|
+
current_context=_build_sql_generation_context(
|
|
789
|
+
conn_params=conn_params,
|
|
790
|
+
schema=schema,
|
|
791
|
+
concept=concept,
|
|
792
|
+
concept_metadata=concept_metadata,
|
|
793
|
+
graph_depth=context_graph_depth,
|
|
794
|
+
include_tags=include_tags,
|
|
795
|
+
exclude_properties=exclude_properties,
|
|
796
|
+
db_is_case_sensitive=db_is_case_sensitive,
|
|
797
|
+
max_limit=max_limit),
|
|
798
|
+
note=evaluation_note + validation_err_txt,
|
|
799
|
+
should_validate_sql=True, # Always validate during reasoning
|
|
800
|
+
timeout=timeout,
|
|
801
|
+
debug=debug,
|
|
802
|
+
)
|
|
803
|
+
|
|
804
|
+
regen_sql = regen_result['sql']
|
|
805
|
+
regen_is_valid = regen_result['is_valid']
|
|
806
|
+
regen_error = regen_result['error']
|
|
807
|
+
|
|
808
|
+
# Track token usage for each validation iteration
|
|
809
|
+
if validation_iteration == 1:
|
|
810
|
+
usage_metadata[f'generate_sql_reasoning_step_{step + 1}'] = {
|
|
811
|
+
"approximate": regen_result['apx_token_count'],
|
|
812
|
+
**regen_result['usage_metadata'],
|
|
813
|
+
}
|
|
814
|
+
if debug and 'p_hash' in regen_result:
|
|
815
|
+
usage_metadata[f'generate_sql_reasoning_step_{step + 1}']['p_hash'] = regen_result['p_hash']
|
|
816
|
+
else:
|
|
817
|
+
usage_metadata[f'generate_sql_reasoning_step_{step + 1}_validation_{validation_iteration}'] = {
|
|
818
|
+
"approximate": regen_result['apx_token_count'],
|
|
819
|
+
**regen_result['usage_metadata'],
|
|
820
|
+
}
|
|
821
|
+
if debug and 'p_hash' in regen_result:
|
|
822
|
+
usage_metadata[f'generate_sql_reasoning_step_{step + 1}_validation_{validation_iteration}']['p_hash'] = regen_result['p_hash']
|
|
798
823
|
|
|
799
|
-
sql_query =
|
|
800
|
-
is_sql_valid =
|
|
801
|
-
error =
|
|
824
|
+
sql_query = regen_sql
|
|
825
|
+
is_sql_valid = regen_is_valid
|
|
826
|
+
error = regen_error
|
|
802
827
|
|
|
803
828
|
except TimeoutError as e:
|
|
804
829
|
raise Exception(f"LLM call timed out: {str(e)}")
|
|
@@ -241,24 +241,36 @@ def get_tags(conn_params: dict, include_tags: Optional[Any] = None) -> dict:
|
|
|
241
241
|
}
|
|
242
242
|
|
|
243
243
|
|
|
244
|
-
def _should_ignore_list(list: list) -> bool:
|
|
244
|
+
def _should_ignore_list(list: list[Any] | None) -> bool:
|
|
245
245
|
return bool(list and len(list) == 1 and (list[0].lower() in ['none', 'null']))
|
|
246
246
|
|
|
247
247
|
|
|
248
|
-
def _should_select_all(list: list) -> bool:
|
|
248
|
+
def _should_select_all(list: list[Any] | None) -> bool:
|
|
249
249
|
return bool(list and len(list) == 1 and list[0] == '*')
|
|
250
250
|
|
|
251
251
|
|
|
252
|
+
def _has_dtimbr_permissions(conn_params: dict) -> bool:
|
|
253
|
+
has_perms = True
|
|
254
|
+
dtimbr_query = "SHOW TABLES IN dtimbr"
|
|
255
|
+
try:
|
|
256
|
+
dtimbr_tables = run_query(dtimbr_query, conn_params)
|
|
257
|
+
has_perms = len(dtimbr_tables) > 0
|
|
258
|
+
except Exception:
|
|
259
|
+
has_perms = False
|
|
260
|
+
|
|
261
|
+
return has_perms
|
|
262
|
+
|
|
263
|
+
|
|
252
264
|
@cache_with_version_check
|
|
253
265
|
def get_concepts(
|
|
254
266
|
conn_params,
|
|
255
|
-
concepts_list: Optional[list] = None,
|
|
256
|
-
views_list: Optional[list] = None,
|
|
267
|
+
concepts_list: Optional[list[Any]] = None,
|
|
268
|
+
views_list: Optional[list[Any]] = None,
|
|
257
269
|
include_logic_concepts: Optional[bool] = False,
|
|
258
270
|
) -> dict:
|
|
259
271
|
"""Fetch concepts (or views) from timbr.sys_concepts and/or timbr.sys_views."""
|
|
260
272
|
joined_views = ','.join(f"'{v}'" for v in views_list) if views_list else ''
|
|
261
|
-
should_ignore_concepts = _should_ignore_list(concepts_list)
|
|
273
|
+
should_ignore_concepts = _should_ignore_list(concepts_list) or not _has_dtimbr_permissions(conn_params)
|
|
262
274
|
should_ignore_views = _should_ignore_list(views_list)
|
|
263
275
|
|
|
264
276
|
filter_concepts = " WHERE concept IN (SELECT DISTINCT concept FROM timbr.sys_concept_properties)" if not include_logic_concepts else ""
|
|
@@ -13,6 +13,8 @@ def config():
|
|
|
13
13
|
"timbr_url": os.environ.get("TIMBR_URL", "https://demo-env.timbr.ai"),
|
|
14
14
|
"timbr_token": os.environ.get("TIMBR_TOKEN"),
|
|
15
15
|
"timbr_ontology": os.environ.get("TIMBR_ONTOLOGY", "supply_metrics_llm_tests"),
|
|
16
|
+
"timbr_token_no_dtimbr_perms": os.environ.get("TIMBR_TOKEN_NO_DTIMBR_PERMS"),
|
|
17
|
+
"timbr_ontology_no_dtimbr_perms": os.environ.get("TIMBR_ONTOLOGY_NO_DTIMBR_PERMS", "timbr_calls"),
|
|
16
18
|
"test_prompt": os.environ.get("TEST_PROMPT", "What are the total sales for consumer customers?"),
|
|
17
19
|
"test_prompt_2": os.environ.get("TEST_PROMPT_2", "Get all customers"),
|
|
18
20
|
"test_prompt_3": os.environ.get("TEST_PROMPT_3", "Get all products and materials"),
|
{langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/tests/integration/test_langchain_chains.py
RENAMED
|
@@ -402,4 +402,17 @@ class TestGenerateAnswerChain:
|
|
|
402
402
|
assert "answer" in result, "Chain should return an 'answer'"
|
|
403
403
|
assert result["answer"], "Answer should not be empty"
|
|
404
404
|
assert chain.usage_metadata_key in result, "Chain should return 'generate_answer_usage_metadata'"
|
|
405
|
-
assert len(result[chain.usage_metadata_key]) == 1 and 'answer_question' in result[chain.usage_metadata_key], "Generate answer chain usage metadata should contain only 'answer_question'"
|
|
405
|
+
assert len(result[chain.usage_metadata_key]) == 1 and 'answer_question' in result[chain.usage_metadata_key], "Generate answer chain usage metadata should contain only 'answer_question'"
|
|
406
|
+
|
|
407
|
+
def test_generate_timbr_sql_with_no_dtimbr_perms(self, llm, config):
|
|
408
|
+
"""Test SQL generation with a user that lacks dtimbr schema permissions."""
|
|
409
|
+
chain = GenerateTimbrSqlChain(
|
|
410
|
+
llm=llm,
|
|
411
|
+
url=config["timbr_url"],
|
|
412
|
+
token=config["timbr_token_no_dtimbr_perms"],
|
|
413
|
+
ontology=config["timbr_ontology_no_dtimbr_perms"],
|
|
414
|
+
verify_ssl=config["verify_ssl"],
|
|
415
|
+
)
|
|
416
|
+
result = chain.invoke({ "prompt": "all calls" })
|
|
417
|
+
print("GenerateTimbrSqlChain with concepts_list=['plant'] result:", result)
|
|
418
|
+
assert "error" in result and "User doesn't have access to query Knowledge Graph schema: dtimbr" in result["error"], "Should return permission error message"
|
|
@@ -29,7 +29,7 @@ class TestLangGraphNodes:
|
|
|
29
29
|
# Create a test state payload.
|
|
30
30
|
state = {
|
|
31
31
|
"prompt": config["test_prompt"],
|
|
32
|
-
"messages": [{ "content": config["test_prompt"] }],
|
|
32
|
+
# "messages": [{ "content": config["test_prompt"] }],
|
|
33
33
|
}
|
|
34
34
|
result = node(state)
|
|
35
35
|
print("IdentifyConceptNode result:", result)
|
|
@@ -111,3 +111,24 @@ class TestLangGraphNodes:
|
|
|
111
111
|
print("GenerateResponseNode result:", result)
|
|
112
112
|
assert "answer" in result, "Result should contain 'answer'"
|
|
113
113
|
assert result["answer"], "Answer should not be empty"
|
|
114
|
+
|
|
115
|
+
def test_execute_node_with_state_graph(self, llm, config):
|
|
116
|
+
"""Test basic ExecuteSemanticQueryNode functionality."""
|
|
117
|
+
from langgraph.graph import StateGraph
|
|
118
|
+
state = StateGraph(dict)
|
|
119
|
+
state.messages = [{"content": config["test_prompt"]}]
|
|
120
|
+
|
|
121
|
+
execute_query_node = ExecuteSemanticQueryNode(
|
|
122
|
+
llm=llm,
|
|
123
|
+
url=config["timbr_url"],
|
|
124
|
+
token=config["timbr_token"],
|
|
125
|
+
ontology=config["timbr_ontology"],
|
|
126
|
+
verify_ssl=config["verify_ssl"],
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
output = execute_query_node(state)
|
|
130
|
+
|
|
131
|
+
print("ExecuteSemanticQueryNode result:", output)
|
|
132
|
+
assert "rows" in output, "Result should contain 'rows'"
|
|
133
|
+
assert isinstance(output["rows"], list), "'rows' should be a list"
|
|
134
|
+
assert output["sql"], "SQL should be present in the result"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/src/langchain_timbr/langchain/timbr_sql_agent.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/src/langchain_timbr/llm_wrapper/llm_wrapper.py
RENAMED
|
File without changes
|
|
File without changes
|
{langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/src/langchain_timbr/timbr_llm_connector.py
RENAMED
|
File without changes
|
|
File without changes
|
{langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/src/langchain_timbr/utils/prompt_service.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/tests/integration/test_agent_integration.py
RENAMED
|
File without changes
|
|
File without changes
|
{langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/tests/integration/test_azure_openai_model.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/tests/integration/test_timeout_functionality.py
RENAMED
|
File without changes
|
|
File without changes
|
{langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/tests/standard/test_chain_documentation.py
RENAMED
|
File without changes
|
{langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/tests/standard/test_connection_validation.py
RENAMED
|
File without changes
|
{langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/tests/standard/test_llm_wrapper_optional_params.py
RENAMED
|
File without changes
|
{langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/tests/standard/test_optional_llm_integration.py
RENAMED
|
File without changes
|
{langchain_timbr-2.1.11 → langchain_timbr-2.1.13}/tests/standard/test_standard_chain_requirements.py
RENAMED
|
File without changes
|
|
File without changes
|