langchain-timbr 2.1.11__tar.gz → 2.1.12__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.
Files changed (58) hide show
  1. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/.github/workflows/install-dependencies-and-run-tests.yml +2 -0
  2. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/PKG-INFO +1 -1
  3. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/src/langchain_timbr/_version.py +2 -2
  4. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/src/langchain_timbr/utils/timbr_llm_utils.py +1 -1
  5. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/src/langchain_timbr/utils/timbr_utils.py +17 -5
  6. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/tests/conftest.py +2 -0
  7. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/tests/integration/test_langchain_chains.py +14 -1
  8. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/.github/dependabot.yml +0 -0
  9. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/.github/pull_request_template.md +0 -0
  10. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/.github/workflows/_codespell.yml +0 -0
  11. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/.github/workflows/_fossa.yml +0 -0
  12. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/.github/workflows/publish.yml +0 -0
  13. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/.gitignore +0 -0
  14. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/LICENSE +0 -0
  15. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/README.md +0 -0
  16. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/SECURITY.md +0 -0
  17. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/pyproject.toml +0 -0
  18. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/pytest.ini +0 -0
  19. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/requirements.txt +0 -0
  20. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/requirements310.txt +0 -0
  21. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/requirements311.txt +0 -0
  22. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/src/langchain_timbr/__init__.py +0 -0
  23. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/src/langchain_timbr/config.py +0 -0
  24. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/src/langchain_timbr/langchain/__init__.py +0 -0
  25. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/src/langchain_timbr/langchain/execute_timbr_query_chain.py +0 -0
  26. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/src/langchain_timbr/langchain/generate_answer_chain.py +0 -0
  27. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/src/langchain_timbr/langchain/generate_timbr_sql_chain.py +0 -0
  28. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/src/langchain_timbr/langchain/identify_concept_chain.py +0 -0
  29. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/src/langchain_timbr/langchain/timbr_sql_agent.py +0 -0
  30. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/src/langchain_timbr/langchain/validate_timbr_sql_chain.py +0 -0
  31. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/src/langchain_timbr/langgraph/__init__.py +0 -0
  32. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/src/langchain_timbr/langgraph/execute_timbr_query_node.py +0 -0
  33. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/src/langchain_timbr/langgraph/generate_response_node.py +0 -0
  34. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/src/langchain_timbr/langgraph/generate_timbr_sql_node.py +0 -0
  35. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/src/langchain_timbr/langgraph/identify_concept_node.py +0 -0
  36. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/src/langchain_timbr/langgraph/validate_timbr_query_node.py +0 -0
  37. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/src/langchain_timbr/llm_wrapper/llm_wrapper.py +0 -0
  38. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/src/langchain_timbr/llm_wrapper/timbr_llm_wrapper.py +0 -0
  39. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/src/langchain_timbr/timbr_llm_connector.py +0 -0
  40. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/src/langchain_timbr/utils/general.py +0 -0
  41. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/src/langchain_timbr/utils/prompt_service.py +0 -0
  42. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/src/langchain_timbr/utils/temperature_supported_models.json +0 -0
  43. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/tests/README.md +0 -0
  44. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/tests/integration/test_agent_integration.py +0 -0
  45. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/tests/integration/test_azure_databricks_provider.py +0 -0
  46. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/tests/integration/test_azure_openai_model.py +0 -0
  47. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/tests/integration/test_chain_pipeline.py +0 -0
  48. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/tests/integration/test_chain_reasoning.py +0 -0
  49. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/tests/integration/test_jwt_token.py +0 -0
  50. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/tests/integration/test_langgraph_nodes.py +0 -0
  51. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/tests/integration/test_timeout_functionality.py +0 -0
  52. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/tests/standard/conftest.py +0 -0
  53. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/tests/standard/test_chain_documentation.py +0 -0
  54. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/tests/standard/test_connection_validation.py +0 -0
  55. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/tests/standard/test_llm_wrapper_optional_params.py +0 -0
  56. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/tests/standard/test_optional_llm_integration.py +0 -0
  57. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/tests/standard/test_standard_chain_requirements.py +0 -0
  58. {langchain_timbr-2.1.11 → langchain_timbr-2.1.12}/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 }}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: langchain-timbr
3
- Version: 2.1.11
3
+ Version: 2.1.12
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.11'
32
- __version_tuple__ = version_tuple = (2, 1, 11)
31
+ __version__ = version = '2.1.12'
32
+ __version_tuple__ = version_tuple = (2, 1, 12)
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -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: # and not (concepts[0].lower() == 'none' or concepts[0].lower() == 'null'):
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:
@@ -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"),
@@ -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"