DeepFabric 4.8.2__tar.gz → 4.9.0__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 (225) hide show
  1. {deepfabric-4.8.2 → deepfabric-4.9.0}/.github/workflows/docs.yml +1 -1
  2. {deepfabric-4.8.2 → deepfabric-4.9.0}/.github/workflows/integration.yml +1 -1
  3. {deepfabric-4.8.2 → deepfabric-4.9.0}/.github/workflows/publish.yml +1 -1
  4. {deepfabric-4.8.2 → deepfabric-4.9.0}/.github/workflows/test.yml +1 -1
  5. deepfabric-4.9.0/CODE_OF_CONDUCT.md +77 -0
  6. deepfabric-4.9.0/CONTRIBUTING.md +256 -0
  7. {deepfabric-4.8.2 → deepfabric-4.9.0}/PKG-INFO +3 -3
  8. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/config.py +5 -0
  9. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/graph.py +51 -11
  10. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/metrics.py +2 -2
  11. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/prompts.py +136 -0
  12. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/schemas.py +3 -1
  13. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/cli/upload.md +1 -0
  14. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/dataset-generation/agent.md +1 -0
  15. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/dataset-generation/configuration.md +27 -2
  16. {deepfabric-4.8.2 → deepfabric-4.9.0}/examples/agent-tools-multi.yaml +1 -0
  17. {deepfabric-4.8.2 → deepfabric-4.9.0}/examples/agent-tools-single.yaml +1 -0
  18. {deepfabric-4.8.2 → deepfabric-4.9.0}/examples/basic-anthropic.yaml +1 -0
  19. {deepfabric-4.8.2 → deepfabric-4.9.0}/examples/basic-gemini.yaml +1 -0
  20. {deepfabric-4.8.2 → deepfabric-4.9.0}/examples/basic-graph.yaml +1 -0
  21. {deepfabric-4.8.2 → deepfabric-4.9.0}/examples/basic-ollama.yaml +1 -0
  22. {deepfabric-4.8.2 → deepfabric-4.9.0}/examples/basic-openai.yaml +1 -0
  23. {deepfabric-4.8.2 → deepfabric-4.9.0}/examples/basic-openrouter.yaml +1 -0
  24. {deepfabric-4.8.2 → deepfabric-4.9.0}/examples/coding-agent.yaml +1 -0
  25. {deepfabric-4.8.2 → deepfabric-4.9.0}/examples/github-mock-tools.yaml +1 -0
  26. {deepfabric-4.8.2 → deepfabric-4.9.0}/examples/reasoning.yaml +1 -0
  27. {deepfabric-4.8.2 → deepfabric-4.9.0}/examples/spin-vfs-tools.yaml +1 -0
  28. {deepfabric-4.8.2 → deepfabric-4.9.0}/examples/tools-sdk-examples/figma/spin-figma.yaml +1 -0
  29. {deepfabric-4.8.2 → deepfabric-4.9.0}/examples/tools-sdk-examples/github/spin-github-tools.yaml +1 -0
  30. {deepfabric-4.8.2 → deepfabric-4.9.0}/examples/tools-sdk-examples/kubernetes/spin-kubernetes.yaml +1 -0
  31. {deepfabric-4.8.2 → deepfabric-4.9.0}/pyproject.toml +3 -3
  32. {deepfabric-4.8.2 → deepfabric-4.9.0}/tests/unit/test_api_key_validation.py +1 -0
  33. {deepfabric-4.8.2 → deepfabric-4.9.0}/tests/unit/test_cli.py +1 -0
  34. {deepfabric-4.8.2 → deepfabric-4.9.0}/tests/unit/test_hf_hub.py +8 -1
  35. {deepfabric-4.8.2 → deepfabric-4.9.0}/uv.lock +61 -22
  36. deepfabric-4.8.2/examples/mcp-adversarial-suite/README.md +0 -269
  37. deepfabric-4.8.2/examples/mcp-adversarial-suite/configs/all.yaml +0 -213
  38. deepfabric-4.8.2/examples/mcp-adversarial-suite/configs/driftlab.yaml +0 -113
  39. deepfabric-4.8.2/examples/mcp-adversarial-suite/configs/homoglyph.yaml +0 -107
  40. deepfabric-4.8.2/examples/mcp-adversarial-suite/configs/insecurefs.yaml +0 -139
  41. deepfabric-4.8.2/examples/mcp-adversarial-suite/configs/resource_trap.yaml +0 -147
  42. deepfabric-4.8.2/examples/mcp-adversarial-suite/configs/spoofbox.yaml +0 -124
  43. {deepfabric-4.8.2 → deepfabric-4.9.0}/.github/config.yml +0 -0
  44. {deepfabric-4.8.2 → deepfabric-4.9.0}/.github/dependabot.yml +0 -0
  45. {deepfabric-4.8.2 → deepfabric-4.9.0}/.github/workflows/tools-sdk-docker.yml +0 -0
  46. {deepfabric-4.8.2 → deepfabric-4.9.0}/.gitignore +0 -0
  47. {deepfabric-4.8.2 → deepfabric-4.9.0}/CLAUDE.md +0 -0
  48. {deepfabric-4.8.2 → deepfabric-4.9.0}/LICENSE +0 -0
  49. {deepfabric-4.8.2 → deepfabric-4.9.0}/Makefile +0 -0
  50. {deepfabric-4.8.2 → deepfabric-4.9.0}/README.md +0 -0
  51. {deepfabric-4.8.2 → deepfabric-4.9.0}/assets/df-demo.gif +0 -0
  52. {deepfabric-4.8.2 → deepfabric-4.9.0}/assets/logo-light-hols.png +0 -0
  53. {deepfabric-4.8.2 → deepfabric-4.9.0}/assets/logo-light.png +0 -0
  54. {deepfabric-4.8.2 → deepfabric-4.9.0}/assets/star.gif +0 -0
  55. {deepfabric-4.8.2 → deepfabric-4.9.0}/coverage.xml +0 -0
  56. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/__init__.py +0 -0
  57. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/__main__.py +0 -0
  58. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/auth.py +0 -0
  59. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/builders.py +0 -0
  60. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/builders_agent.py +0 -0
  61. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/cli.py +0 -0
  62. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/cloud_upload.py +0 -0
  63. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/config_manager.py +0 -0
  64. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/constants.py +0 -0
  65. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/dataset.py +0 -0
  66. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/dataset_manager.py +0 -0
  67. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/error_codes.py +0 -0
  68. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/evaluation/__init__.py +0 -0
  69. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/evaluation/backends/__init__.py +0 -0
  70. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/evaluation/backends/llm_eval_backend.py +0 -0
  71. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/evaluation/backends/ollama_backend.py +0 -0
  72. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/evaluation/backends/tool_call_parsers.py +0 -0
  73. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/evaluation/backends/transformers_backend.py +0 -0
  74. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/evaluation/evaluator.py +0 -0
  75. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/evaluation/evaluators/__init__.py +0 -0
  76. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/evaluation/evaluators/base.py +0 -0
  77. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/evaluation/evaluators/builtin/__init__.py +0 -0
  78. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/evaluation/evaluators/builtin/tool_calling.py +0 -0
  79. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/evaluation/evaluators/registry.py +0 -0
  80. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/evaluation/inference.py +0 -0
  81. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/evaluation/metrics.py +0 -0
  82. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/evaluation/parser.py +0 -0
  83. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/evaluation/reporters/__init__.py +0 -0
  84. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/evaluation/reporters/base.py +0 -0
  85. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/evaluation/reporters/cloud_reporter.py +0 -0
  86. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/evaluation/reporters/file_reporter.py +0 -0
  87. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/evaluation/reporters/multi_reporter.py +0 -0
  88. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/exceptions.py +0 -0
  89. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/factory.py +0 -0
  90. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/generator.py +0 -0
  91. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/hf_hub.py +0 -0
  92. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/kaggle_hub.py +0 -0
  93. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/llm/__init__.py +0 -0
  94. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/llm/api_key_verifier.py +0 -0
  95. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/llm/client.py +0 -0
  96. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/llm/errors.py +0 -0
  97. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/llm/rate_limit_config.py +0 -0
  98. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/llm/rate_limit_detector.py +0 -0
  99. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/llm/retry_handler.py +0 -0
  100. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/loader.py +0 -0
  101. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/progress.py +0 -0
  102. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/spin/__init__.py +0 -0
  103. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/spin/client.py +0 -0
  104. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/spin/models.py +0 -0
  105. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/stream_simulator.py +0 -0
  106. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/tools/__init__.py +0 -0
  107. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/tools/defaults.py +0 -0
  108. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/tools/loader.py +0 -0
  109. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/tools/mcp_client.py +0 -0
  110. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/topic_manager.py +0 -0
  111. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/topic_model.py +0 -0
  112. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/training/__init__.py +0 -0
  113. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/training/api_key_prompt.py +0 -0
  114. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/training/callback.py +0 -0
  115. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/training/dataset_utils.py +0 -0
  116. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/training/metrics_sender.py +0 -0
  117. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/tree.py +0 -0
  118. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/tui.py +0 -0
  119. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/update_checker.py +0 -0
  120. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/utils.py +0 -0
  121. {deepfabric-4.8.2 → deepfabric-4.9.0}/deepfabric/validation.py +0 -0
  122. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/cli/evaluate.md +0 -0
  123. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/cli/generate.md +0 -0
  124. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/cli/import-tools.md +0 -0
  125. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/cli/index.md +0 -0
  126. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/cli/info.md +0 -0
  127. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/cli/upload-hf.md +0 -0
  128. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/cli/upload-kaggle.md +0 -0
  129. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/cli/validate.md +0 -0
  130. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/cli/visualize.md +0 -0
  131. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/dataset-generation/basic.md +0 -0
  132. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/dataset-generation/index.md +0 -0
  133. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/dataset-generation/rate-limiting.md +0 -0
  134. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/dataset-generation/reasoning.md +0 -0
  135. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/evaluation/index.md +0 -0
  136. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/evaluation/metrics.md +0 -0
  137. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/evaluation/running.md +0 -0
  138. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/images/logo-light.png +0 -0
  139. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/images/python-spin.png +0 -0
  140. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/index.md +0 -0
  141. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/tools/custom.md +0 -0
  142. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/tools/index.md +0 -0
  143. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/tools/mock.md +0 -0
  144. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/tools/spin.md +0 -0
  145. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/tools/tutorials/go.md +0 -0
  146. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/tools/tutorials/index.md +0 -0
  147. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/tools/tutorials/python.md +0 -0
  148. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/tools/tutorials/rust.md +0 -0
  149. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/tools/tutorials/typescript.md +0 -0
  150. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/tools/vfs.md +0 -0
  151. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/training/chat-templates.md +0 -0
  152. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/training/dataset-preparation.md +0 -0
  153. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/training/frameworks.md +0 -0
  154. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/training/index.md +0 -0
  155. {deepfabric-4.8.2 → deepfabric-4.9.0}/docs/training/loading.md +0 -0
  156. {deepfabric-4.8.2 → deepfabric-4.9.0}/examples/basic-tree.yaml +0 -0
  157. {deepfabric-4.8.2 → deepfabric-4.9.0}/examples/complete.yaml +0 -0
  158. {deepfabric-4.8.2 → deepfabric-4.9.0}/examples/custom-tools.yaml +0 -0
  159. {deepfabric-4.8.2 → deepfabric-4.9.0}/examples/tools-sdk-examples/blender/load-blender-mock-data.sh +0 -0
  160. {deepfabric-4.8.2 → deepfabric-4.9.0}/examples/tools-sdk-examples/blender/spin-blender.yaml +0 -0
  161. {deepfabric-4.8.2 → deepfabric-4.9.0}/examples/tools-sdk-examples/figma/load-figma-mock-data.sh +0 -0
  162. {deepfabric-4.8.2 → deepfabric-4.9.0}/examples/tools-sdk-examples/github/load-github-mock-data.sh +0 -0
  163. {deepfabric-4.8.2 → deepfabric-4.9.0}/examples/tools-sdk-examples/kubernetes/load-kubernetes-mock-data.sh +0 -0
  164. {deepfabric-4.8.2 → deepfabric-4.9.0}/misc/test_update_manual.py +0 -0
  165. {deepfabric-4.8.2 → deepfabric-4.9.0}/mkdocs.yml +0 -0
  166. {deepfabric-4.8.2 → deepfabric-4.9.0}/notebooks/Train_and_Evaluate_Qwen3_4B_Thinking_as_a_Blender_MCP_Agent.ipynb +0 -0
  167. {deepfabric-4.8.2 → deepfabric-4.9.0}/notebooks/dataset-compatibility-check.ipynb +0 -0
  168. {deepfabric-4.8.2 → deepfabric-4.9.0}/notebooks/evaluations.ipynb +0 -0
  169. {deepfabric-4.8.2 → deepfabric-4.9.0}/test-run/01-alpaca.txt +0 -0
  170. {deepfabric-4.8.2 → deepfabric-4.9.0}/test-run/01-chatml.txt +0 -0
  171. {deepfabric-4.8.2 → deepfabric-4.9.0}/test-run/01-grpo.txt +0 -0
  172. {deepfabric-4.8.2 → deepfabric-4.9.0}/test-run/01-xlam_v2.txt +0 -0
  173. {deepfabric-4.8.2 → deepfabric-4.9.0}/test-run/02-trl2.txt +0 -0
  174. {deepfabric-4.8.2 → deepfabric-4.9.0}/test-run/02-xlam_v2.txt +0 -0
  175. {deepfabric-4.8.2 → deepfabric-4.9.0}/test-run/04-agent-tool-conversations.jsnl +0 -0
  176. {deepfabric-4.8.2 → deepfabric-4.9.0}/test-run/04-single-agent-tools +0 -0
  177. {deepfabric-4.8.2 → deepfabric-4.9.0}/tests/__init__.py +0 -0
  178. {deepfabric-4.8.2 → deepfabric-4.9.0}/tests/integration/__init__.py +0 -0
  179. {deepfabric-4.8.2 → deepfabric-4.9.0}/tests/integration/conftest.py +0 -0
  180. {deepfabric-4.8.2 → deepfabric-4.9.0}/tests/integration/test_generator_integration.py +0 -0
  181. {deepfabric-4.8.2 → deepfabric-4.9.0}/tests/integration/test_graph_integration.py +0 -0
  182. {deepfabric-4.8.2 → deepfabric-4.9.0}/tests/integration/test_llm_client_integration.py +0 -0
  183. {deepfabric-4.8.2 → deepfabric-4.9.0}/tests/integration/test_spin_integration.py +0 -0
  184. {deepfabric-4.8.2 → deepfabric-4.9.0}/tests/integration/test_tree_integration.py +0 -0
  185. {deepfabric-4.8.2 → deepfabric-4.9.0}/tests/unit/__init__.py +0 -0
  186. {deepfabric-4.8.2 → deepfabric-4.9.0}/tests/unit/conftest.py +0 -0
  187. {deepfabric-4.8.2 → deepfabric-4.9.0}/tests/unit/test_cloud_upload.py +0 -0
  188. {deepfabric-4.8.2 → deepfabric-4.9.0}/tests/unit/test_config.py +0 -0
  189. {deepfabric-4.8.2 → deepfabric-4.9.0}/tests/unit/test_dataset.py +0 -0
  190. {deepfabric-4.8.2 → deepfabric-4.9.0}/tests/unit/test_error_codes.py +0 -0
  191. {deepfabric-4.8.2 → deepfabric-4.9.0}/tests/unit/test_gemini_schema.py +0 -0
  192. {deepfabric-4.8.2 → deepfabric-4.9.0}/tests/unit/test_generator.py +0 -0
  193. {deepfabric-4.8.2 → deepfabric-4.9.0}/tests/unit/test_kaggle_hub.py +0 -0
  194. {deepfabric-4.8.2 → deepfabric-4.9.0}/tests/unit/test_llm_eval_backend.py +0 -0
  195. {deepfabric-4.8.2 → deepfabric-4.9.0}/tests/unit/test_loader.py +0 -0
  196. {deepfabric-4.8.2 → deepfabric-4.9.0}/tests/unit/test_modular_config.py +0 -0
  197. {deepfabric-4.8.2 → deepfabric-4.9.0}/tests/unit/test_rate_limiting.py +0 -0
  198. {deepfabric-4.8.2 → deepfabric-4.9.0}/tests/unit/test_schemas.py +0 -0
  199. {deepfabric-4.8.2 → deepfabric-4.9.0}/tests/unit/test_tool_call_parsers.py +0 -0
  200. {deepfabric-4.8.2 → deepfabric-4.9.0}/tests/unit/test_topic_graph.py +0 -0
  201. {deepfabric-4.8.2 → deepfabric-4.9.0}/tests/unit/test_training_callback.py +0 -0
  202. {deepfabric-4.8.2 → deepfabric-4.9.0}/tests/unit/test_update_checker.py +0 -0
  203. {deepfabric-4.8.2 → deepfabric-4.9.0}/tools/extract_messages.py +0 -0
  204. {deepfabric-4.8.2 → deepfabric-4.9.0}/tools/function.py +0 -0
  205. {deepfabric-4.8.2 → deepfabric-4.9.0}/tools/yaml_to_openai_tools.py +0 -0
  206. {deepfabric-4.8.2 → deepfabric-4.9.0}/tools-sdk/.dockerignore +0 -0
  207. {deepfabric-4.8.2 → deepfabric-4.9.0}/tools-sdk/Dockerfile +0 -0
  208. {deepfabric-4.8.2 → deepfabric-4.9.0}/tools-sdk/README.md +0 -0
  209. {deepfabric-4.8.2 → deepfabric-4.9.0}/tools-sdk/components/github/README.md +0 -0
  210. {deepfabric-4.8.2 → deepfabric-4.9.0}/tools-sdk/components/github/app.py +0 -0
  211. {deepfabric-4.8.2 → deepfabric-4.9.0}/tools-sdk/components/github/github.wasm +0 -0
  212. {deepfabric-4.8.2 → deepfabric-4.9.0}/tools-sdk/components/github/pyproject.toml +0 -0
  213. {deepfabric-4.8.2 → deepfabric-4.9.0}/tools-sdk/components/github/requirements.txt +0 -0
  214. {deepfabric-4.8.2 → deepfabric-4.9.0}/tools-sdk/components/github/spin.toml +0 -0
  215. {deepfabric-4.8.2 → deepfabric-4.9.0}/tools-sdk/components/github/uv.lock +0 -0
  216. {deepfabric-4.8.2 → deepfabric-4.9.0}/tools-sdk/components/mock/Cargo.lock +0 -0
  217. {deepfabric-4.8.2 → deepfabric-4.9.0}/tools-sdk/components/mock/Cargo.toml +0 -0
  218. {deepfabric-4.8.2 → deepfabric-4.9.0}/tools-sdk/components/mock/README.md +0 -0
  219. {deepfabric-4.8.2 → deepfabric-4.9.0}/tools-sdk/components/mock/src/lib.rs +0 -0
  220. {deepfabric-4.8.2 → deepfabric-4.9.0}/tools-sdk/components/vfs/Cargo.lock +0 -0
  221. {deepfabric-4.8.2 → deepfabric-4.9.0}/tools-sdk/components/vfs/Cargo.toml +0 -0
  222. {deepfabric-4.8.2 → deepfabric-4.9.0}/tools-sdk/components/vfs/src/lib.rs +0 -0
  223. {deepfabric-4.8.2 → deepfabric-4.9.0}/tools-sdk/docker-compose.yaml +0 -0
  224. {deepfabric-4.8.2 → deepfabric-4.9.0}/tools-sdk/runtime-config.toml +0 -0
  225. {deepfabric-4.8.2 → deepfabric-4.9.0}/tools-sdk/spin.toml +0 -0
@@ -23,7 +23,7 @@ jobs:
23
23
  uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v5
24
24
 
25
25
  - name: Install uv
26
- uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7
26
+ uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7
27
27
 
28
28
  - name: Set up Python
29
29
  run: uv python install
@@ -58,7 +58,7 @@ jobs:
58
58
  cache: pip
59
59
 
60
60
  - name: Install uv
61
- uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7
61
+ uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7
62
62
  with:
63
63
  enable-cache: true
64
64
 
@@ -24,7 +24,7 @@ jobs:
24
24
  python-version: '3.x'
25
25
 
26
26
  - name: Install uv
27
- uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7
27
+ uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7
28
28
 
29
29
  - name: Build distributions
30
30
  run: uv build
@@ -22,7 +22,7 @@ jobs:
22
22
  python-version: ${{ matrix.python-version }}
23
23
 
24
24
  - name: Install uv
25
- uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7
25
+ uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7
26
26
  with:
27
27
  enable-cache: true
28
28
 
@@ -0,0 +1,77 @@
1
+
2
+ # Contributor Covenant Code of Conduct
3
+
4
+ ## Our Pledge
5
+
6
+ In the interest of fostering an open and welcoming environment, we as
7
+ contributors and maintainers pledge to make participation in our project and
8
+ our community a harassment-free experience for everyone, regardless of age, body
9
+ size, disability, ethnicity, sex characteristics, gender identity and expression,
10
+ level of experience, education, socio-economic status, nationality, personal
11
+ appearance, race, religion, or sexual identity and orientation.
12
+
13
+ ## Our Standards
14
+
15
+ Examples of behavior that contributes to creating a positive environment
16
+ include:
17
+
18
+ * Using welcoming and inclusive language
19
+ * Being respectful of differing viewpoints and experiences
20
+ * Gracefully accepting constructive criticism
21
+ * Focusing on what is best for the community
22
+ * Showing empathy towards other community members
23
+
24
+ Examples of unacceptable behavior by participants include:
25
+
26
+ * The use of sexualized language or imagery and unwelcome sexual attention or
27
+ advances
28
+ * Trolling, insulting/derogatory comments, and personal or political attacks
29
+ * Public or private harassment
30
+ * Publishing others' private information, such as a physical or electronic
31
+ address, without explicit permission
32
+ * Other conduct which could reasonably be considered inappropriate in a
33
+ professional setting
34
+
35
+ ## Our Responsibilities
36
+
37
+ Project maintainers are responsible for clarifying the standards of acceptable
38
+ behavior and are expected to take appropriate and fair corrective action in
39
+ response to any instances of unacceptable behavior.
40
+
41
+ Project maintainers have the right and responsibility to remove, edit, or
42
+ reject comments, commits, code, wiki edits, issues, and other contributions
43
+ that are not aligned to this Code of Conduct, or to ban temporarily or
44
+ permanently any contributor for other behaviors that they deem inappropriate,
45
+ threatening, offensive, or harmful.
46
+
47
+ ## Scope
48
+
49
+ This Code of Conduct applies within all project spaces, and it also applies when
50
+ an individual is representing the project or its community in public spaces.
51
+ Examples of representing a project or community include using an official
52
+ project e-mail address, posting via an official social media account, or acting
53
+ as an appointed representative at an online or offline event. Representation of
54
+ a project may be further defined and clarified by project maintainers.
55
+
56
+ ## Enforcement
57
+
58
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
59
+ reported by contacting the project team at [hello@alwaysfurther.ai](mailto:hello@alwaysfurther.ai).
60
+ All complaints will be reviewed and investigated and will result in a response that
61
+ is deemed necessary and appropriate to the circumstances. The project team is
62
+ obligated to maintain confidentiality with regard to the reporter of an incident.
63
+ Further details of specific enforcement policies may be posted separately.
64
+
65
+ Project maintainers who do not follow or enforce the Code of Conduct in good
66
+ faith may face temporary or permanent repercussions as determined by other
67
+ members of the project's leadership.
68
+
69
+ ## Attribution
70
+
71
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
72
+ available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
73
+
74
+ [homepage]: https://www.contributor-covenant.org
75
+
76
+ For answers to common questions about this code of conduct, see
77
+ https://www.contributor-covenant.org/faq
@@ -0,0 +1,256 @@
1
+ ## Contributing
2
+
3
+ Thank you for considering contributing to [deepfabric](https://github.com/always-further/deepfabric)!
4
+
5
+ When contributing, please first discuss the change you wish to make via [issue](https://github.com/always-further/deepfabric/issues), [email](mailto:hello@alwaysfurther.ai), or any other method with the owners of this repository before making a change.
6
+
7
+ Note that we have a [Code of Conduct](./CODE_OF_CONDUCT.md), please follow it in all your interactions with the project.
8
+
9
+ ## Setup
10
+
11
+ ### Prerequisites
12
+
13
+ - **Python 3.10 or later**
14
+
15
+ ## Development
16
+
17
+ ### 1. Fork and clone the repository
18
+
19
+ Fork this repository and create your branch from `main`.
20
+
21
+ ```sh
22
+ git clone https://github.com/<YOUR-USERNAME>/deepfabric
23
+ cd deepfabric
24
+ ```
25
+
26
+ ### 2. Create and activate a virtual environment
27
+
28
+ We strongly recommend using an isolated virtual environment.
29
+
30
+ #### Option A: Using `venv` (standard Python)
31
+
32
+ ```sh
33
+ python -m venv .venv
34
+ source .venv/bin/activate
35
+ ```
36
+
37
+ #### Option B: Using [`uv`](https://docs.astral.sh/uv/) (recommended)
38
+
39
+ DeepFabric supports running all development tasks via [`uv`](https://docs.astral.sh/uv/), which provides fast and reproducible environments without manual virtual environment activation.
40
+
41
+ ### 3. Install the project and development dependencies
42
+
43
+ DeepFabric uses [PEP 621 (pyproject.toml)](https://peps.python.org/pep-0621/) with [Hatch](https://hatch.pypa.io/latest/) as the build backend.
44
+
45
+ <details>
46
+ <summary>Option A: Standard Python (`venv` + `pip`)</summary>
47
+
48
+ ```sh
49
+ # Make sure your virtual environment is activated.
50
+ pip install -U pip
51
+ pip install -e '.[dev]'
52
+ ```
53
+ </details>
54
+
55
+ <details>
56
+ <summary>Option B: Using `uv` (recommended)</summary>
57
+
58
+ ```sh
59
+ uv sync --extra dev
60
+ ```
61
+ </details>
62
+
63
+ This installs:
64
+ - test dependencies (`pytest`, `pytest-cov`, etc.)
65
+ - linting and security tools (`ruff`, `bandit`)
66
+
67
+ ### 4. Run the test suite
68
+
69
+ Ensure all tests pass before submitting changes.
70
+
71
+ #### Unit tests (required)
72
+
73
+ At a minimum, please run the unit test suite. Additional integration and security checks are recommended when relevant.
74
+
75
+ <details>
76
+ <summary>Option A: Standard Python (`venv` + `pip`)</summary>
77
+
78
+ ```sh
79
+ # Make sure your virtual environment is activated.
80
+ pytest tests/unit/
81
+ ```
82
+ </details>
83
+
84
+ <details>
85
+ <summary>Option B: Using `uv` (recommended)</summary>
86
+
87
+ ```sh
88
+ uv run pytest tests/unit/
89
+ ```
90
+ </details>
91
+
92
+ #### Integration tests (optional, but recommended)
93
+
94
+ Integration tests cover interactions with external systems (e.g. LLM providers). They may require additional environment variables or credentials.
95
+ Please refer to the [Makefile](./Makefile) for available integration test targets.
96
+
97
+ #### Security checks (optional)
98
+
99
+ We recommend running security checks before submitting larger or user-facing changes.
100
+
101
+ <details>
102
+ <summary>Option A: Standard Python (`venv` + `pip`)</summary>
103
+
104
+ ```sh
105
+ # Make sure your virtual environment is activated.
106
+ bandit -r deepfabric/
107
+ ```
108
+ </details>
109
+
110
+ <details>
111
+ <summary>Option B: Using `uv` (recommended)</summary>
112
+
113
+ ```sh
114
+ uv run bandit -r deepfabric/
115
+ ```
116
+ </details>
117
+
118
+ ### 5. Lint and format the code
119
+
120
+ Ensure the codebase is properly linted and formatted before submitting changes.
121
+
122
+ <details>
123
+ <summary>Option A: Standard Python (`venv` + `pip`)</summary>
124
+
125
+ ```sh
126
+ # Make sure your virtual environment is activated.
127
+ ruff format deepfabric/ tests/
128
+ ruff check . --exclude notebooks/
129
+ ```
130
+ </details>
131
+
132
+ <details>
133
+ <summary>Option B: Using `uv` (recommended)</summary>
134
+
135
+ ```sh
136
+ uv run ruff format deepfabric/ tests/
137
+ uv run ruff check . --exclude notebooks/
138
+ ```
139
+ </details>
140
+
141
+ ### 6. Commit your changes
142
+
143
+ We strongly recommend following the [Conventional Commits specification](https://www.conventionalcommits.org/en/v1.0.0/) when committing:
144
+
145
+ - **feat:** new features
146
+ - **fix:** bug fixes
147
+ - **docs:** documentation-only changes
148
+ - **refactor:** code refactoring
149
+ - **test:** adding or updating tests
150
+ - **chore:** tooling and maintenance
151
+
152
+ Example:
153
+
154
+ ```sh
155
+ git commit -m "feat: add dataset validation pipeline"
156
+ ```
157
+
158
+ ## Documentation
159
+
160
+ ### 1. Install documentation dependencies
161
+
162
+ DeepFabric uses [MkDocs](https://www.mkdocs.org/) with the [Material theme](https://squidfunk.github.io/mkdocs-material/) for documentation.
163
+
164
+ <details>
165
+ <summary>Option A: Standard Python (`venv` + `pip`)</summary>
166
+
167
+ ```sh
168
+ # Make sure your virtual environment is activated.
169
+ pip install -U pip
170
+ pip install -e '.[docs]'
171
+ ```
172
+ </details>
173
+
174
+ <details>
175
+ <summary>Option B: Using `uv` (recommended)</summary>
176
+
177
+ ```sh
178
+ uv sync --extra docs
179
+ ```
180
+ </details>
181
+
182
+ This installs:
183
+ - MkDocs and the Material theme (`mkdocs-material`)
184
+ - Python API documentation support via `mkdocstrings[python]`
185
+
186
+ ### 2. Writing documentation
187
+
188
+ - User-facing documentation lives in the [docs](./docs) directory.
189
+ - API documentation is generated from [Python docstrings](https://peps.python.org/pep-0257/) via `mkdocstrings`.
190
+ - Please follow the existing style and structure when adding new pages.
191
+
192
+ ### 3. Docstring conventions
193
+
194
+ DeepFabric enforces [Google-style docstrings](https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings), consistent with the `ruff` configuration:
195
+
196
+ ```toml
197
+ [tool.ruff.lint.pydocstyle]
198
+ convention = "google"
199
+ ```
200
+
201
+ Example:
202
+
203
+ ```python
204
+ def load_dataset(path: str) -> Dataset:
205
+ """Load a dataset from disk.
206
+
207
+ Args:
208
+ path: Path to the dataset directory.
209
+
210
+ Returns:
211
+ The loaded dataset.
212
+ """
213
+ ...
214
+ ```
215
+
216
+ ### 4. Serve the documentation locally
217
+
218
+ Ensure you can preview the documentation site locally before submitting changes.
219
+
220
+ <details>
221
+ <summary>Option A: Standard Python (`venv` + `pip`)</summary>
222
+
223
+ ```sh
224
+ # Make sure your virtual environment is activated.
225
+ mkdocs serve
226
+ ```
227
+ </details>
228
+
229
+ <details>
230
+ <summary>Option B: Using `uv` (recommended)</summary>
231
+
232
+ ```sh
233
+ uv run mkdocs serve
234
+ ```
235
+ </details>
236
+
237
+ ### 5. Build the documentation
238
+
239
+ Ensure you generate the static documentation site before publishing or submitting changes.
240
+
241
+ <details>
242
+ <summary>Option A: Standard Python (`venv` + `pip`)</summary>
243
+
244
+ ```sh
245
+ # Make sure your virtual environment is activated.
246
+ mkdocs build
247
+ ```
248
+ </details>
249
+
250
+ <details>
251
+ <summary>Option B: Using `uv` (recommended)</summary>
252
+
253
+ ```sh
254
+ uv run mkdocs build
255
+ ```
256
+ </details>
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: DeepFabric
3
- Version: 4.8.2
3
+ Version: 4.9.0
4
4
  Summary: Curate High Quality Datasets, Train, Evaluate and Ship
5
5
  Author-email: DeepFabric Team <oss@alwaysfurther.ai>
6
6
  License-File: LICENSE
@@ -11,7 +11,7 @@ Requires-Dist: componentize-py>=0.19.3
11
11
  Requires-Dist: datasets<5.0,>=3.0
12
12
  Requires-Dist: google-api-core>=2.0.0
13
13
  Requires-Dist: google-genai>=1.56.0
14
- Requires-Dist: huggingface-hub==0.36.0
14
+ Requires-Dist: huggingface-hub>=1.3.1
15
15
  Requires-Dist: kagglehub>=0.3.0
16
16
  Requires-Dist: mermaid-py>=0.8.0
17
17
  Requires-Dist: ollama>=0.6.1
@@ -25,7 +25,7 @@ Requires-Dist: pyyaml>=6.0.1
25
25
  Requires-Dist: rich>=13.0.0
26
26
  Requires-Dist: sentencepiece>=0.1.99
27
27
  Requires-Dist: spin-sdk>=3.4.1
28
- Requires-Dist: transformers>=4.57.1
28
+ Requires-Dist: transformers==5.0.0rc2
29
29
  Provides-Extra: dev
30
30
  Requires-Dist: bandit>=1.7.10; extra == 'dev'
31
31
  Requires-Dist: mermaid-py>=0.2.0; extra == 'dev'
@@ -109,6 +109,10 @@ class TopicsConfig(BaseModel):
109
109
  description="Maximum concurrent LLM calls during graph expansion (helps avoid rate limits)",
110
110
  )
111
111
  save_as: str | None = Field(default=None, description="Where to save the generated topics")
112
+ prompt_style: Literal["default", "isolated", "anchored"] = Field(
113
+ default="default",
114
+ description="For graph mode: 'default' enables cross-connections with generic prompts, 'isolated' disables connections with generic prompts, 'anchored' disables connections and uses domain-aware prompts with examples for focused topic generation",
115
+ )
112
116
 
113
117
  # Optional LLM overrides (inherits from top-level llm if not specified)
114
118
  llm: LLMConfig | None = Field(
@@ -603,6 +607,7 @@ See documentation for full examples.
603
607
  "depth": self.topics.depth,
604
608
  "degree": self.topics.degree,
605
609
  "max_concurrent": self.topics.max_concurrent,
610
+ "prompt_style": self.topics.prompt_style,
606
611
  }
607
612
 
608
613
  # Handle overrides
@@ -5,7 +5,7 @@ import textwrap
5
5
  import uuid
6
6
 
7
7
  from datetime import datetime, timezone
8
- from typing import TYPE_CHECKING, Any
8
+ from typing import TYPE_CHECKING, Any, Literal
9
9
 
10
10
  from pydantic import BaseModel, ConfigDict, Field
11
11
 
@@ -19,7 +19,11 @@ from .constants import (
19
19
  from .llm import LLMClient
20
20
  from .llm.rate_limit_detector import RateLimitDetector
21
21
  from .metrics import trace
22
- from .prompts import GRAPH_EXPANSION_PROMPT
22
+ from .prompts import (
23
+ GRAPH_EXPANSION_PROMPT,
24
+ GRAPH_EXPANSION_PROMPT_NO_CONNECTIONS,
25
+ GraphPromptBuilder,
26
+ )
23
27
  from .schemas import GraphSubtopics
24
28
  from .stream_simulator import simulate_stream
25
29
  from .topic_model import TopicModel
@@ -70,6 +74,10 @@ class GraphConfig(BaseModel):
70
74
  default=None,
71
75
  description="Base URL for API endpoint (e.g., custom OpenAI-compatible servers)",
72
76
  )
77
+ prompt_style: Literal["default", "isolated", "anchored"] = Field(
78
+ default="default",
79
+ description="Prompt style: 'default' (cross-connections, generic), 'isolated' (no connections, generic), 'anchored' (no connections, domain-aware)",
80
+ )
73
81
 
74
82
 
75
83
  class GraphMetadata(BaseModel):
@@ -148,6 +156,7 @@ class Graph(TopicModel):
148
156
  self.degree = self.config.degree
149
157
  self.depth = self.config.depth
150
158
  self.max_concurrent = self.config.max_concurrent
159
+ self.prompt_style = self.config.prompt_style
151
160
 
152
161
  # Initialize LLM client
153
162
  llm_kwargs = {}
@@ -493,6 +502,17 @@ class Graph(TopicModel):
493
502
  )
494
503
  return None
495
504
 
505
+ def _get_path_to_node(self, node: Node) -> list[str]:
506
+ """Get the topic path from root to the given node."""
507
+ path = []
508
+ current = node
509
+ while current is not None:
510
+ path.append(current.topic)
511
+ # First parent is the primary parent from tree expansion;
512
+ # cross-connections are added later and appear after index 0
513
+ current = current.parents[0] if current.parents else None
514
+ return list(reversed(path))
515
+
496
516
  async def get_subtopics_and_connections(
497
517
  self, parent_node: Node, num_subtopics: int
498
518
  ) -> tuple[int, int]:
@@ -505,15 +525,35 @@ class Graph(TopicModel):
505
525
  Returns:
506
526
  A tuple of (subtopics_added, connections_added).
507
527
  """
508
- graph_summary = (
509
- self.to_json()
510
- if len(self.nodes) <= TOPIC_GRAPH_SUMMARY
511
- else "Graph too large to display"
512
- )
513
-
514
- graph_prompt = GRAPH_EXPANSION_PROMPT.replace("{{current_graph_summary}}", graph_summary)
515
- graph_prompt = graph_prompt.replace("{{current_topic}}", parent_node.topic)
516
- graph_prompt = graph_prompt.replace("{{num_subtopics}}", str(num_subtopics))
528
+ # Choose prompt based on prompt_style setting
529
+ if self.prompt_style == "anchored":
530
+ # Domain-aware prompts with examples for focused generation
531
+ topic_path = self._get_path_to_node(parent_node)
532
+ domain = GraphPromptBuilder.detect_domain(self.model_system_prompt, topic_path)
533
+ graph_prompt = GraphPromptBuilder.build_anchored_prompt(
534
+ topic_path=topic_path,
535
+ num_subtopics=num_subtopics,
536
+ system_prompt=self.model_system_prompt,
537
+ domain=domain,
538
+ )
539
+ elif self.prompt_style == "isolated":
540
+ # No connections, generic prompt
541
+ graph_prompt = GRAPH_EXPANSION_PROMPT_NO_CONNECTIONS.replace(
542
+ "{{current_topic}}", parent_node.topic
543
+ )
544
+ graph_prompt = graph_prompt.replace("{{num_subtopics}}", str(num_subtopics))
545
+ else:
546
+ # default: cross-connections enabled, generic prompt
547
+ graph_summary = (
548
+ self.to_json()
549
+ if len(self.nodes) <= TOPIC_GRAPH_SUMMARY
550
+ else "Graph too large to display"
551
+ )
552
+ graph_prompt = GRAPH_EXPANSION_PROMPT.replace(
553
+ "{{current_graph_summary}}", graph_summary
554
+ )
555
+ graph_prompt = graph_prompt.replace("{{current_topic}}", parent_node.topic)
556
+ graph_prompt = graph_prompt.replace("{{num_subtopics}}", str(num_subtopics))
517
557
 
518
558
  response = await self._generate_subtopics_with_retry(graph_prompt, parent_node)
519
559
  if response is None:
@@ -19,8 +19,8 @@ except (ImportError, importlib.metadata.PackageNotFoundError):
19
19
 
20
20
  # Initialize PostHog client
21
21
  posthog = Posthog(
22
- project_api_key="phc_Kn8hKQIXHm5OHp5OTxvMvFDUmT7HyOUNlJvWkduB9qO",
23
- host="https://us.i.posthog.com",
22
+ project_api_key="phc_JZWiTzIDNnBp6Jj6uUb0JQKuIp3dv0gkay9aU50n38h",
23
+ host="https://eu.i.posthog.com",
24
24
  )
25
25
 
26
26
  logger = logging.getLogger(__name__)
@@ -264,6 +264,142 @@ Generate a list of {{num_subtopics}} subtopics. For each subtopic, provide:
264
264
  2. A "connections" list of IDs of existing topics it should connect to for creating cross-links (use empty list if no connections)
265
265
  """
266
266
 
267
+ GRAPH_EXPANSION_PROMPT_NO_CONNECTIONS = """
268
+ You are an expert in topic generation. Your task is to expand a topic into a set of focused subtopics.
269
+
270
+ You are expanding the topic: "{{current_topic}}"
271
+
272
+ Generate a list of {{num_subtopics}} subtopics. For each subtopic, provide:
273
+ 1. A "topic" string - the name of the new subtopic
274
+ 2. A "connections" list - ALWAYS use an empty list []
275
+
276
+ IMPORTANT: Do NOT create cross-connections between topics. Each subtopic should be independent and directly related only to its parent topic. Always return connections as an empty list [].
277
+ """
278
+
279
+
280
+ class GraphPromptBuilder:
281
+ """Build domain-aware prompts for graph topic expansion with anchoring examples."""
282
+
283
+ MAX_PROMPT_EXAMPLES = 3
284
+
285
+ SECURITY_KEYWORDS = frozenset(
286
+ {
287
+ "security",
288
+ "attack",
289
+ "credential",
290
+ "exfiltration",
291
+ "injection",
292
+ "malicious",
293
+ "adversarial",
294
+ "threat",
295
+ }
296
+ )
297
+
298
+ # Domain-specific expansion examples - formatted to match GraphSubtopics schema
299
+ EXAMPLES = {
300
+ "security": [
301
+ {
302
+ "path": ["Security Threats", "Credential Access"],
303
+ "subtopics": [
304
+ {"topic": "reading .env files", "connections": []},
305
+ {"topic": "extracting API keys", "connections": []},
306
+ {"topic": "accessing SSH keys", "connections": []},
307
+ {"topic": "dumping AWS credentials", "connections": []},
308
+ {"topic": "stealing database passwords", "connections": []},
309
+ ],
310
+ },
311
+ {
312
+ "path": ["Security Threats", "Data Exfiltration"],
313
+ "subtopics": [
314
+ {"topic": "sending to webhooks", "connections": []},
315
+ {"topic": "encoding in base64", "connections": []},
316
+ {"topic": "uploading to external URLs", "connections": []},
317
+ {"topic": "email forwarding", "connections": []},
318
+ {"topic": "DNS tunneling", "connections": []},
319
+ ],
320
+ },
321
+ ],
322
+ "technical": [
323
+ {
324
+ "path": ["Programming", "Python"],
325
+ "subtopics": [
326
+ {"topic": "pandas", "connections": []},
327
+ {"topic": "flask", "connections": []},
328
+ {"topic": "pytest", "connections": []},
329
+ {"topic": "asyncio", "connections": []},
330
+ {"topic": "django", "connections": []},
331
+ ],
332
+ },
333
+ {
334
+ "path": ["Infrastructure", "Kubernetes"],
335
+ "subtopics": [
336
+ {"topic": "pods", "connections": []},
337
+ {"topic": "deployments", "connections": []},
338
+ {"topic": "services", "connections": []},
339
+ {"topic": "ingress", "connections": []},
340
+ {"topic": "helm charts", "connections": []},
341
+ ],
342
+ },
343
+ ],
344
+ }
345
+
346
+ @classmethod
347
+ def build_anchored_prompt(
348
+ cls,
349
+ topic_path: list[str],
350
+ num_subtopics: int,
351
+ system_prompt: str = "",
352
+ domain: str = "technical",
353
+ ) -> str:
354
+ """Build a domain-anchored prompt for graph expansion.
355
+
356
+ Returns a prompt that produces focused, on-topic subtopics by providing
357
+ domain-specific examples and the full topic path context.
358
+ """
359
+ path_str = " -> ".join(f'"{topic}"' for topic in topic_path)
360
+ examples = cls._format_examples(cls.EXAMPLES.get(domain, cls.EXAMPLES["technical"]))
361
+
362
+ return f"""Generate {num_subtopics} subtopics for training data organization.
363
+
364
+ Task: Create diverse but related subtopics that expand on the given topic path.
365
+
366
+ Examples:
367
+ {examples}
368
+
369
+ Context: {system_prompt}
370
+
371
+ Topic path: {path_str}
372
+
373
+ Generate {num_subtopics} subtopics. For each subtopic, provide:
374
+ 1. A "topic" string - a specific, concrete subtopic directly related to the parent
375
+ 2. A "connections" list - ALWAYS use an empty list []
376
+
377
+ Return focused subtopics that stay on-topic with the path above."""
378
+
379
+ @classmethod
380
+ def _format_examples(cls, examples: list) -> str:
381
+ """Format examples for inclusion in prompt."""
382
+ formatted = []
383
+ for ex in examples[: cls.MAX_PROMPT_EXAMPLES]:
384
+ path_str = " -> ".join(f'"{topic}"' for topic in ex["path"])
385
+ subtopics_str = str(ex["subtopics"])
386
+ formatted.append(f"Path: {path_str}\nSubtopics: {subtopics_str}")
387
+ return "\n\n".join(formatted)
388
+
389
+ @classmethod
390
+ def detect_domain(cls, system_prompt: str, topic_path: list[str]) -> str:
391
+ """Detect the appropriate domain for prompt examples based on context.
392
+
393
+ Returns 'security' or 'technical' based on keywords in the system prompt
394
+ and topic path. Defaults to 'technical' if no security keywords found.
395
+ """
396
+ combined_text = f"{system_prompt} {' '.join(topic_path)}".lower()
397
+
398
+ if any(word in combined_text for word in cls.SECURITY_KEYWORDS):
399
+ return "security"
400
+ return "technical"
401
+
402
+
267
403
  # Chain of Thought prompts for reasoning-based dataset generation
268
404
  FREETEXT_COT_PROMPT = """Generate a reasoning problem that requires analytical thinking to solve.
269
405
 
@@ -136,7 +136,9 @@ class MCPInputSchemaProperty(BaseModel):
136
136
 
137
137
  model_config = {"extra": "allow"}
138
138
 
139
- type: str | list[str] = Field(default="string", description="JSON Schema type (string or array for nullable)")
139
+ type: str | list[str] = Field(
140
+ default="string", description="JSON Schema type (string or array for nullable)"
141
+ )
140
142
  description: str = Field(default="", description="Property description")
141
143
  default: Any | None = Field(default=None, description="Default value")
142
144