sqlseed 0.1.19__tar.gz → 0.2.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 (71) hide show
  1. {sqlseed-0.1.19 → sqlseed-0.2.0}/CHANGELOG.md +11 -1
  2. {sqlseed-0.1.19 → sqlseed-0.2.0}/CHANGELOG.zh-CN.md +11 -1
  3. {sqlseed-0.1.19 → sqlseed-0.2.0}/PKG-INFO +32 -6
  4. {sqlseed-0.1.19 → sqlseed-0.2.0}/README.md +31 -5
  5. {sqlseed-0.1.19 → sqlseed-0.2.0}/README.zh-CN.md +35 -13
  6. {sqlseed-0.1.19 → sqlseed-0.2.0}/examples/notebooks/02-column-mapping.ipynb +1 -1
  7. sqlseed-0.2.0/scripts/_create_demo_db.py +52 -0
  8. sqlseed-0.2.0/scripts/quickstart.py +179 -0
  9. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/cli/main.py +11 -5
  10. {sqlseed-0.1.19 → sqlseed-0.2.0}/uv.lock +11 -5
  11. {sqlseed-0.1.19 → sqlseed-0.2.0}/.gitignore +0 -0
  12. {sqlseed-0.1.19 → sqlseed-0.2.0}/LICENSE +0 -0
  13. {sqlseed-0.1.19 → sqlseed-0.2.0}/examples/build_demo_db.py +0 -0
  14. {sqlseed-0.1.19 → sqlseed-0.2.0}/examples/notebooks/01-quickstart.ipynb +0 -0
  15. {sqlseed-0.1.19 → sqlseed-0.2.0}/examples/notebooks/03-generators.ipynb +0 -0
  16. {sqlseed-0.1.19 → sqlseed-0.2.0}/examples/notebooks/04-database-advanced.ipynb +0 -0
  17. {sqlseed-0.1.19 → sqlseed-0.2.0}/examples/notebooks/05-dag-and-constraints.ipynb +0 -0
  18. {sqlseed-0.1.19 → sqlseed-0.2.0}/examples/notebooks/06-config-deep-dive.ipynb +0 -0
  19. {sqlseed-0.1.19 → sqlseed-0.2.0}/examples/notebooks/07-ai-plugin.ipynb +0 -0
  20. {sqlseed-0.1.19 → sqlseed-0.2.0}/examples/notebooks/08-mcp-server.ipynb +0 -0
  21. {sqlseed-0.1.19 → sqlseed-0.2.0}/examples/notebooks/09-plugin-hooks.ipynb +0 -0
  22. {sqlseed-0.1.19 → sqlseed-0.2.0}/examples/notebooks/10-cli-reference.ipynb +0 -0
  23. {sqlseed-0.1.19 → sqlseed-0.2.0}/examples/notebooks/11-utilities.ipynb +0 -0
  24. {sqlseed-0.1.19 → sqlseed-0.2.0}/examples/notebooks/12-testing-patterns.ipynb +0 -0
  25. {sqlseed-0.1.19 → sqlseed-0.2.0}/pyproject.toml +0 -0
  26. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/__init__.py +0 -0
  27. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/_utils/__init__.py +0 -0
  28. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/_utils/logger.py +0 -0
  29. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/_utils/metrics.py +0 -0
  30. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/_utils/paths.py +0 -0
  31. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/_utils/progress.py +0 -0
  32. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/_utils/schema_helpers.py +0 -0
  33. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/_utils/sql_safe.py +0 -0
  34. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/_version.py +0 -0
  35. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/cli/__init__.py +0 -0
  36. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/config/__init__.py +0 -0
  37. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/config/loader.py +0 -0
  38. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/config/models.py +0 -0
  39. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/config/snapshot.py +0 -0
  40. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/core/__init__.py +0 -0
  41. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/core/column_dag.py +0 -0
  42. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/core/constraints.py +0 -0
  43. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/core/enrichment.py +0 -0
  44. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/core/expression.py +0 -0
  45. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/core/mapper.py +0 -0
  46. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/core/orchestrator.py +0 -0
  47. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/core/plugin_mediator.py +0 -0
  48. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/core/relation.py +0 -0
  49. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/core/result.py +0 -0
  50. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/core/schema.py +0 -0
  51. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/core/transform.py +0 -0
  52. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/core/unique_adjuster.py +0 -0
  53. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/database/__init__.py +0 -0
  54. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/database/_base_adapter.py +0 -0
  55. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/database/_compat.py +0 -0
  56. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/database/_helpers.py +0 -0
  57. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/database/_protocol.py +0 -0
  58. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/database/optimizer.py +0 -0
  59. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/database/raw_sqlite_adapter.py +0 -0
  60. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/database/sqlite_utils_adapter.py +0 -0
  61. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/generators/__init__.py +0 -0
  62. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/generators/_dispatch.py +0 -0
  63. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/generators/_json_helpers.py +0 -0
  64. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/generators/_protocol.py +0 -0
  65. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/generators/_string_helpers.py +0 -0
  66. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/generators/base_provider.py +0 -0
  67. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/generators/faker_provider.py +0 -0
  68. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/generators/mimesis_provider.py +0 -0
  69. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/generators/registry.py +0 -0
  70. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/generators/stream.py +0 -0
  71. {sqlseed-0.1.19 → sqlseed-0.2.0}/src/sqlseed/py.typed +0 -0
@@ -7,6 +7,16 @@ All notable changes to this project will be documented in this file.
7
7
  Format based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
8
8
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
9
9
 
10
+ ## [v0.1.20]
11
+
12
+ ### Changed
13
+
14
+ - Extracted shared `_col()` test helper from `test_mapper.py` and `test_mapper_camelcase.py` into `conftest.make_column_info()`, eliminating 23-line code duplication (CodeFlow R0801, CodeDuplication; SonarCloud Code Smell)
15
+
16
+ ### Fixed
17
+
18
+ - Merged duplicate test functions `test_non_sensitive_order_no_still_integer` and `test_snake_case_still_works` in `test_mapper_camelcase.py` via `pytest.mark.parametrize` (SonarCloud Major)
19
+
10
20
  ## [v0.1.19]
11
21
 
12
22
  ### Added
@@ -109,7 +119,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
109
119
  - `ColumnMapper` exact match rules expanded from 68 to 74
110
120
 
111
121
  #### AI Plugin (sqlseed-ai)
112
- - Auto model selection: `_model_selector` picks the best free model from OpenRouter by priority
122
+ - Auto model selection: `_model_selector` picks the best Gemma 4 model by priority (26B MoE → 31B Dense → 4B → 2B), with multi-backend support (Google AI Studio, LM Studio, Ollama)
113
123
  - Structured output: `response_format: json_object` forces LLM to return JSON
114
124
  - Few-shot example library: 4 typical scenarios (users, projects, orders, employees)
115
125
  - `AiConfigRefiner` self-correction loop: auto-detects and fixes invalid configs, up to 3 retries
@@ -7,6 +7,16 @@
7
7
  格式基于 [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
8
8
  本项目遵循[语义化版本](https://semver.org/spec/v2.0.0.html)。
9
9
 
10
+ ## [v0.1.20]
11
+
12
+ ### 变更
13
+
14
+ - 将 `test_mapper.py` 和 `test_mapper_camelcase.py` 中重复的 `_col()` 测试辅助函数提取到 `conftest.make_column_info()`,消除 23 行代码重复(CodeFlow R0801、CodeDuplication;SonarCloud Code Smell)
15
+
16
+ ### 修复
17
+
18
+ - 合并 `test_mapper_camelcase.py` 中重复的测试函数 `test_non_sensitive_order_no_still_integer` 和 `test_snake_case_still_works`,使用 `pytest.mark.parametrize` 参数化(SonarCloud Major)
19
+
10
20
  ## [v0.1.19]
11
21
 
12
22
  ### 新增
@@ -109,7 +119,7 @@
109
119
  - `ColumnMapper` 精确匹配规则从 68 扩展到 74 条
110
120
 
111
121
  #### AI 插件(sqlseed-ai)
112
- - 自动模型选择:`_model_selector` OpenRouter 免费模型列表中按优先级自动选择
122
+ - 自动模型选择:`_model_selector` Gemma 4 优先级自动选择(26B MoE → 31B Dense → 4B → 2B),支持多后端(Google AI Studio、LM Studio、Ollama)
113
123
  - 结构化输出:`response_format: json_object` 强制 LLM 返回 JSON
114
124
  - Few-shot 示例库:4 个典型场景(用户表、银行卡表、订单表、员工表)
115
125
  - `AiConfigRefiner` 自纠正闭环:自动检测并修复无效配置,最多 3 轮重试
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlseed
3
- Version: 0.1.19
3
+ Version: 0.2.0
4
4
  Summary: Declarative SQLite test data generation toolkit
5
5
  Project-URL: Homepage, https://github.com/sunbos/sqlseed
6
6
  Project-URL: Documentation, https://github.com/sunbos/sqlseed#readme
@@ -240,6 +240,12 @@ mypy src/sqlseed/
240
240
 
241
241
  ## 🚀 Quick Start
242
242
 
243
+ ### Interactive Quickstart
244
+
245
+ ```bash
246
+ python scripts/quickstart.py
247
+ ```
248
+
243
249
  ### Try with Demo Database
244
250
 
245
251
  Want to try sqlseed right away? Build the demo database:
@@ -712,7 +718,6 @@ pip install sqlseed-ai
712
718
 
713
719
  # Set API key
714
720
  export SQLSEED_AI_API_KEY="your-api-key"
715
- export SQLSEED_AI_BASE_URL="https://your-llm-api-endpoint"
716
721
 
717
722
  # AI analysis and config generation
718
723
  sqlseed ai-suggest app.db --table projects --output projects.yaml
@@ -720,9 +725,27 @@ sqlseed ai-suggest app.db --table projects --output projects.yaml
720
725
  # AI suggestions with self-correction (3 rounds by default)
721
726
  sqlseed ai-suggest app.db --table projects --output projects.yaml --verify
722
727
 
723
- # Specify model (defaults to most popular free model)
724
- sqlseed ai-suggest app.db --table projects --output projects.yaml --model nvidia/nemotron-3-super-120b-a12b:free
728
+ # Specify model (defaults to Gemma 4 26B via Google AI Studio)
729
+ sqlseed ai-suggest app.db --table projects --output projects.yaml --model gemma-4-26b-it
730
+
731
+ # Use local LM Studio / Ollama
732
+ sqlseed ai-suggest app.db --table projects --output projects.yaml --backend lm_studio --model google/gemma-4-e4b
733
+ ```
725
734
 
735
+ **Gemma 4 Native Function Calling (GEMMA_TOOLS)**:
736
+
737
+ sqlseed-ai supports Gemma 4 model family (2B/4B/26B/31B) with Native Function Calling via GEMMA_TOOLS protocol. Supported backends:
738
+
739
+ | Backend | Description | Configuration |
740
+ | :------ | :---------- | :------------ |
741
+ | **Google AI Studio** | Official API, recommended for Gemma 4 26B/31B | `--backend google_ai_studio` or `SQLSEED_AI_BACKEND=google_ai_studio` |
742
+ | **LM Studio** | Local inference, suitable for Gemma 4 2B/4B | `--backend lm_studio` or `SQLSEED_AI_BACKEND=lm_studio` |
743
+ | **Ollama** | Local inference, suitable for Gemma 4 2B/4B/26B | `--backend ollama` or `SQLSEED_AI_BACKEND=ollama` |
744
+ | **OpenAI-compatible** | Generic OpenAI-compatible endpoint (e.g., OpenRouter, DeepSeek) | `--backend openai_compat` or `SQLSEED_AI_BACKEND=openai_compat` |
745
+
746
+ > **💡 OpenRouter (Free)**: For users without a paid API key, OpenRouter provides free models. Set `SQLSEED_AI_BACKEND=openai_compat`, `SQLSEED_AI_BASE_URL=https://openrouter.ai/api/v1`, and `SQLSEED_AI_MODEL=<free-model-name>`.
747
+
748
+ ```bash
726
749
  # Skip cache
727
750
  sqlseed ai-suggest app.db --table projects --output projects.yaml --no-cache
728
751
  ```
@@ -738,7 +761,7 @@ sqlseed ai-suggest app.db --table projects --output projects.yaml --no-cache
738
761
  6. Up to 3 self-correction rounds, outputs validated YAML config
739
762
  ```
740
763
 
741
- > **💡 Environment Variables**: Supports `SQLSEED_AI_API_KEY`, `SQLSEED_AI_BASE_URL`, `SQLSEED_AI_MODEL`. Also supports `OPENAI_API_KEY` / `OPENAI_BASE_URL` as fallback. Defaults to auto-selecting the most popular free model from OpenRouter (base_url `https://openrouter.ai/api/v1`). Set `--model` or `SQLSEED_AI_MODEL` to specify a model.
764
+ > **💡 Environment Variables**: Supports `SQLSEED_AI_API_KEY`, `SQLSEED_AI_BASE_URL`, `SQLSEED_AI_MODEL`, `SQLSEED_AI_BACKEND`. Also supports `OPENAI_API_KEY` / `OPENAI_BASE_URL` as fallback. Defaults to Gemma 4 26B via Google AI Studio. Supported backends: `google_ai_studio`, `lm_studio`, `ollama`, `openai_compat`.
742
765
 
743
766
  ***
744
767
 
@@ -777,6 +800,9 @@ python -m mcp_server_sqlseed
777
800
  | 🔍 Tool | `sqlseed_inspect_schema` | Inspect schema (columns, FK, indexes, samples, schema_hash) |
778
801
  | 🤖 Tool | `sqlseed_generate_yaml` | AI-driven YAML config generation with self-correction. Supports `api_key`/`base_url`/`model` overrides |
779
802
  | ⚡ Tool | `sqlseed_execute_fill` | Execute data generation (supports YAML config string, includes `enrich` option) |
803
+ | 🧠 Tool | `sqlseed_gemma4_analyze` | Analyze schema using Gemma 4 with Native Function Calling |
804
+ | 🧠 Tool | `sqlseed_gemma4_agent_fill` | End-to-end Agent workflow (analyze -> config -> fill) |
805
+ | 🧠 Tool | `sqlseed_list_gemma_models` | List available Gemma 4 models and backend status |
780
806
 
781
807
  This means you can tell your AI assistant:
782
808
 
@@ -1053,7 +1079,7 @@ Tests cover all core modules, with path structure mirroring `src/`: `test_core/`
1053
1079
  | `sqlseed[faker]` | + faker>=30.0 | Faker data engine |
1054
1080
  | `sqlseed[mimesis]` | + mimesis>=18.0 | Mimesis data engine (recommended) |
1055
1081
  | `sqlseed[docs]` | + mkdocs-material, mkdocstrings | Documentation build |
1056
- | `sqlseed-ai` | sqlseed, **openai>=1.0** | AI plugin, auto-registered via entry-point |
1082
+ | `sqlseed-ai` | sqlseed, **openai>=1.0**, **google-generativeai>=0.8** | AI plugin (Gemma 4 Native Function Calling), auto-registered via entry-point |
1057
1083
  | `mcp-server-sqlseed` | sqlseed, **mcp>=1.0** | MCP server, standalone CLI tool |
1058
1084
  | `mcp-server-sqlseed[ai]` | + sqlseed-ai | MCP server with AI support |
1059
1085
 
@@ -180,6 +180,12 @@ mypy src/sqlseed/
180
180
 
181
181
  ## 🚀 Quick Start
182
182
 
183
+ ### Interactive Quickstart
184
+
185
+ ```bash
186
+ python scripts/quickstart.py
187
+ ```
188
+
183
189
  ### Try with Demo Database
184
190
 
185
191
  Want to try sqlseed right away? Build the demo database:
@@ -652,7 +658,6 @@ pip install sqlseed-ai
652
658
 
653
659
  # Set API key
654
660
  export SQLSEED_AI_API_KEY="your-api-key"
655
- export SQLSEED_AI_BASE_URL="https://your-llm-api-endpoint"
656
661
 
657
662
  # AI analysis and config generation
658
663
  sqlseed ai-suggest app.db --table projects --output projects.yaml
@@ -660,9 +665,27 @@ sqlseed ai-suggest app.db --table projects --output projects.yaml
660
665
  # AI suggestions with self-correction (3 rounds by default)
661
666
  sqlseed ai-suggest app.db --table projects --output projects.yaml --verify
662
667
 
663
- # Specify model (defaults to most popular free model)
664
- sqlseed ai-suggest app.db --table projects --output projects.yaml --model nvidia/nemotron-3-super-120b-a12b:free
668
+ # Specify model (defaults to Gemma 4 26B via Google AI Studio)
669
+ sqlseed ai-suggest app.db --table projects --output projects.yaml --model gemma-4-26b-it
670
+
671
+ # Use local LM Studio / Ollama
672
+ sqlseed ai-suggest app.db --table projects --output projects.yaml --backend lm_studio --model google/gemma-4-e4b
673
+ ```
665
674
 
675
+ **Gemma 4 Native Function Calling (GEMMA_TOOLS)**:
676
+
677
+ sqlseed-ai supports Gemma 4 model family (2B/4B/26B/31B) with Native Function Calling via GEMMA_TOOLS protocol. Supported backends:
678
+
679
+ | Backend | Description | Configuration |
680
+ | :------ | :---------- | :------------ |
681
+ | **Google AI Studio** | Official API, recommended for Gemma 4 26B/31B | `--backend google_ai_studio` or `SQLSEED_AI_BACKEND=google_ai_studio` |
682
+ | **LM Studio** | Local inference, suitable for Gemma 4 2B/4B | `--backend lm_studio` or `SQLSEED_AI_BACKEND=lm_studio` |
683
+ | **Ollama** | Local inference, suitable for Gemma 4 2B/4B/26B | `--backend ollama` or `SQLSEED_AI_BACKEND=ollama` |
684
+ | **OpenAI-compatible** | Generic OpenAI-compatible endpoint (e.g., OpenRouter, DeepSeek) | `--backend openai_compat` or `SQLSEED_AI_BACKEND=openai_compat` |
685
+
686
+ > **💡 OpenRouter (Free)**: For users without a paid API key, OpenRouter provides free models. Set `SQLSEED_AI_BACKEND=openai_compat`, `SQLSEED_AI_BASE_URL=https://openrouter.ai/api/v1`, and `SQLSEED_AI_MODEL=<free-model-name>`.
687
+
688
+ ```bash
666
689
  # Skip cache
667
690
  sqlseed ai-suggest app.db --table projects --output projects.yaml --no-cache
668
691
  ```
@@ -678,7 +701,7 @@ sqlseed ai-suggest app.db --table projects --output projects.yaml --no-cache
678
701
  6. Up to 3 self-correction rounds, outputs validated YAML config
679
702
  ```
680
703
 
681
- > **💡 Environment Variables**: Supports `SQLSEED_AI_API_KEY`, `SQLSEED_AI_BASE_URL`, `SQLSEED_AI_MODEL`. Also supports `OPENAI_API_KEY` / `OPENAI_BASE_URL` as fallback. Defaults to auto-selecting the most popular free model from OpenRouter (base_url `https://openrouter.ai/api/v1`). Set `--model` or `SQLSEED_AI_MODEL` to specify a model.
704
+ > **💡 Environment Variables**: Supports `SQLSEED_AI_API_KEY`, `SQLSEED_AI_BASE_URL`, `SQLSEED_AI_MODEL`, `SQLSEED_AI_BACKEND`. Also supports `OPENAI_API_KEY` / `OPENAI_BASE_URL` as fallback. Defaults to Gemma 4 26B via Google AI Studio. Supported backends: `google_ai_studio`, `lm_studio`, `ollama`, `openai_compat`.
682
705
 
683
706
  ***
684
707
 
@@ -717,6 +740,9 @@ python -m mcp_server_sqlseed
717
740
  | 🔍 Tool | `sqlseed_inspect_schema` | Inspect schema (columns, FK, indexes, samples, schema_hash) |
718
741
  | 🤖 Tool | `sqlseed_generate_yaml` | AI-driven YAML config generation with self-correction. Supports `api_key`/`base_url`/`model` overrides |
719
742
  | ⚡ Tool | `sqlseed_execute_fill` | Execute data generation (supports YAML config string, includes `enrich` option) |
743
+ | 🧠 Tool | `sqlseed_gemma4_analyze` | Analyze schema using Gemma 4 with Native Function Calling |
744
+ | 🧠 Tool | `sqlseed_gemma4_agent_fill` | End-to-end Agent workflow (analyze -> config -> fill) |
745
+ | 🧠 Tool | `sqlseed_list_gemma_models` | List available Gemma 4 models and backend status |
720
746
 
721
747
  This means you can tell your AI assistant:
722
748
 
@@ -993,7 +1019,7 @@ Tests cover all core modules, with path structure mirroring `src/`: `test_core/`
993
1019
  | `sqlseed[faker]` | + faker>=30.0 | Faker data engine |
994
1020
  | `sqlseed[mimesis]` | + mimesis>=18.0 | Mimesis data engine (recommended) |
995
1021
  | `sqlseed[docs]` | + mkdocs-material, mkdocstrings | Documentation build |
996
- | `sqlseed-ai` | sqlseed, **openai>=1.0** | AI plugin, auto-registered via entry-point |
1022
+ | `sqlseed-ai` | sqlseed, **openai>=1.0**, **google-generativeai>=0.8** | AI plugin (Gemma 4 Native Function Calling), auto-registered via entry-point |
997
1023
  | `mcp-server-sqlseed` | sqlseed, **mcp>=1.0** | MCP server, standalone CLI tool |
998
1024
  | `mcp-server-sqlseed[ai]` | + sqlseed-ai | MCP server with AI support |
999
1025
 
@@ -178,6 +178,14 @@ mypy src/sqlseed/
178
178
 
179
179
  ## 🚀 快速开始
180
180
 
181
+ ### 一键体验脚本
182
+
183
+ ```bash
184
+ python scripts/quickstart.py
185
+ ```
186
+
187
+ 该脚本会自动创建示例数据库、填充数据并展示结果,适合首次体验。
188
+
181
189
  ### 使用示例数据库体验
182
190
 
183
191
  想立即体验 sqlseed?构建示例数据库:
@@ -553,22 +561,27 @@ sqlseed ai-suggest app.db --table projects --output projects.yaml
553
561
  # 带自纠正的 AI 建议(默认 3 轮修正)
554
562
  sqlseed ai-suggest app.db --table projects --output projects.yaml --verify
555
563
 
556
- # 指定模型
557
- sqlseed ai-suggest app.db --table projects -o projects.yaml --model deepseek/deepseek-chat
564
+ # 指定模型(支持多后端:Google AI Studio、LM Studio、Ollama、OpenAI-compatible)
565
+ sqlseed ai-suggest app.db --table projects -o projects.yaml --model gemma-4-26b-it --backend google_ai_studio
566
+ sqlseed ai-suggest app.db --table projects -o projects.yaml --model gemma-4-31b-it --backend google_ai_studio
567
+ sqlseed ai-suggest app.db --table projects -o projects.yaml --model google/gemma-4-e4b --backend lm_studio
568
+ sqlseed ai-suggest app.db --table projects -o projects.yaml --model gemma-4-4b-it --backend ollama
558
569
  ```
559
570
 
560
- **AI 工作流程**:
571
+ **Gemma 4 原生函数调用(GEMMA_TOOLS)**:
561
572
 
562
- ```
563
- 1. 提取 Schema 上下文(列信息、索引、样本数据、外键、数据分布)
564
- 2. 构建带 Few-shot 示例的 LLM Prompt
565
- 3. LLM 返回 JSON 格式的列配置建议
566
- 4. AiConfigRefiner 自动验证配置的正确性
567
- 5. 若发现错误,自动向 LLM 发送修正请求
568
- 6. 最多 3 轮自纠正,输出经过验证的 YAML 配置
569
- ```
573
+ sqlseed-ai 支持 Gemma 4 系列模型(2B/4B/26B/31B)通过 GEMMA_TOOLS 协议实现原生函数调用,无需 JSON Mode 模拟。支持的后端:
574
+
575
+ | 后端 | 说明 | 配置方式 |
576
+ | :--- | :--- | :--- |
577
+ | **Google AI Studio** | 官方 API,推荐 Gemma 4 26B/31B | `--backend google_ai_studio` 或 `SQLSEED_AI_BACKEND=google_ai_studio` |
578
+ | **LM Studio** | 本地推理,适合 Gemma 4 2B/4B | `--backend lm_studio` 或 `SQLSEED_AI_BACKEND=lm_studio` |
579
+ | **Ollama** | 本地推理,适合 Gemma 4 2B/4B/26B | `--backend ollama` 或 `SQLSEED_AI_BACKEND=ollama` |
580
+ | **OpenAI-compatible** | 通用 OpenAI 兼容端点(如 OpenRouter、DeepSeek) | `--backend openai_compat` 或 `SQLSEED_AI_BACKEND=openai_compat` |
570
581
 
571
- > **💡 环境变量**:支持 `SQLSEED_AI_API_KEY`、`SQLSEED_AI_BASE_URL`、`SQLSEED_AI_MODEL`。也支持 `OPENAI_API_KEY` / `OPENAI_BASE_URL` 作为回退。
582
+ > **💡 OpenRouter(免费方案)**:没有付费 API Key 的用户,可以使用 OpenRouter 的免费模型。设置 `SQLSEED_AI_BACKEND=openai_compat`、`SQLSEED_AI_BASE_URL=https://openrouter.ai/api/v1`、`SQLSEED_AI_MODEL=<免费模型名>`。
583
+
584
+ > **💡 环境变量**:支持 `SQLSEED_AI_API_KEY`、`SQLSEED_AI_BASE_URL`、`SQLSEED_AI_MODEL`、`SQLSEED_AI_BACKEND`。也支持 `OPENAI_API_KEY` / `OPENAI_BASE_URL` 作为回退。
572
585
 
573
586
  ***
574
587
 
@@ -598,6 +611,9 @@ pip install mcp-server-sqlseed[ai]
598
611
  | 🔍 Tool | `sqlseed_inspect_schema` | 检查 Schema(列、外键、索引、样本数据、schema_hash) |
599
612
  | 🤖 Tool | `sqlseed_generate_yaml` | AI 驱动的 YAML 配置生成(含自纠正) |
600
613
  | ⚡ Tool | `sqlseed_execute_fill` | 执行数据生成(支持 YAML 配置字符串,含 `enrich` 选项) |
614
+ | 🤖 Tool | `sqlseed_gemma4_analyze` | Gemma 4 原生函数调用分析 Schema(GEMMA_TOOLS 协议) |
615
+ | 🤖 Tool | `sqlseed_gemma4_agent_fill` | Gemma 4 Agent 模式端到端数据生成(分析→配置→填充) |
616
+ | 📋 Tool | `sqlseed_list_gemma_models` | 列出可用的 Gemma 4 模型及后端支持情况 |
601
617
 
602
618
  ***
603
619
 
@@ -679,6 +695,12 @@ sqlseed ai-suggest app.db -t users -o users.yaml --verify
679
695
  sqlseed ai-suggest app.db -t users -o users.yaml --api-key sk-xxx --base-url https://api.openai.com/v1
680
696
  sqlseed ai-suggest app.db -t users -o users.yaml --max-retries 0
681
697
  sqlseed ai-suggest app.db -t users -o users.yaml --no-cache
698
+
699
+ # ═══ AI 后端选择 ═══
700
+ sqlseed ai-suggest app.db -t users -o users.yaml --backend google_ai_studio --model gemma-4-26b-it
701
+ sqlseed ai-suggest app.db -t users -o users.yaml --backend ollama --model gemma-4-4b-it
702
+ sqlseed ai-suggest app.db -t users -o users.yaml --backend lm_studio --model google/gemma-4-e4b
703
+ sqlseed ai-suggest app.db -t users -o users.yaml --backend openai_compat --model your-model --base-url https://your-api-endpoint
682
704
  ```
683
705
 
684
706
  ***
@@ -805,7 +827,7 @@ mypy src/sqlseed/ # 类型检查
805
827
  | `sqlseed[faker]` | + faker>=30.0 | Faker 数据引擎 |
806
828
  | `sqlseed[mimesis]` | + mimesis>=18.0 | Mimesis 数据引擎(推荐) |
807
829
  | `sqlseed[docs]` | + mkdocs-material, mkdocstrings | 文档构建 |
808
- | `sqlseed-ai` | sqlseed, **openai>=1.0** | AI 插件,通过 entry-point 自动注册 |
830
+ | `sqlseed-ai` | sqlseed, **openai>=1.0**, **google-generativeai>=0.8** | AI 插件,通过 entry-point 自动注册,支持 Gemma 4 GEMMA_TOOLS |
809
831
  | `mcp-server-sqlseed` | sqlseed, **mcp>=1.0** | MCP 服务器,独立 CLI 工具 |
810
832
  | `mcp-server-sqlseed[ai]` | + sqlseed-ai | MCP 服务器含 AI 支持 |
811
833
 
@@ -1353,7 +1353,7 @@
1353
1353
  " fk_columns = {fk.column for fk in fk_info}\n",
1354
1354
  " print(\"members 表列映射分析:\")\n",
1355
1355
  " for col in col_info:\n",
1356
- " if col.name.endswith(\"_id\") or col.name.endswith(\"_no\"):\n",
1356
+ " if col.name.endswith((\"_id\", \"_no\")):\n",
1357
1357
  " is_fk = col.name in fk_columns\n",
1358
1358
  " gen_type = \"foreign_key\" if is_fk else \"integer/string\"\n",
1359
1359
  " print(f\" {col.name}: {gen_type} (FK={is_fk})\")"
@@ -0,0 +1,52 @@
1
+ """Create demo database with 3 tables for quickstart script."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import sqlite3
6
+ import sys
7
+ from pathlib import Path
8
+
9
+
10
+ def main() -> None:
11
+ db_path_str = sys.argv[1] if len(sys.argv) > 1 else "quickstart_demo.db"
12
+ db_path = Path(db_path_str)
13
+ if db_path.exists():
14
+ db_path.unlink()
15
+
16
+ conn = sqlite3.connect(str(db_path))
17
+ conn.executescript("""
18
+ CREATE TABLE users (
19
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
20
+ name TEXT NOT NULL,
21
+ email TEXT NOT NULL UNIQUE,
22
+ age INTEGER,
23
+ city TEXT,
24
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP
25
+ );
26
+ CREATE TABLE projects (
27
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
28
+ name TEXT NOT NULL,
29
+ description TEXT,
30
+ status TEXT DEFAULT 'Planning',
31
+ owner_id INTEGER REFERENCES users(id),
32
+ budget REAL,
33
+ deadline DATE,
34
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP
35
+ );
36
+ CREATE TABLE orders (
37
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
38
+ user_id INTEGER REFERENCES users(id),
39
+ project_id INTEGER REFERENCES projects(id),
40
+ amount REAL NOT NULL,
41
+ status TEXT DEFAULT 'pending',
42
+ order_date DATE,
43
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP
44
+ );
45
+ """)
46
+ conn.commit()
47
+ conn.close()
48
+ print(f" Database created: {db_path} (3 tables: users, projects, orders)")
49
+
50
+
51
+ if __name__ == "__main__":
52
+ main()
@@ -0,0 +1,179 @@
1
+ #!/usr/bin/env python
2
+ """sqlseed + Gemma 4 one-click setup script (cross-platform).
3
+
4
+ Usage:
5
+ python scripts/quickstart.py [--backend lm_studio|ollama|google] [--model MODEL_NAME]
6
+ python scripts/quickstart.py --skip-install # Skip pip install, use current env
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import argparse
12
+ import os
13
+ import subprocess
14
+ import sys
15
+ import urllib.request
16
+ from pathlib import Path
17
+
18
+ PROJECT_ROOT = Path(__file__).resolve().parent.parent
19
+ DB_PATH = PROJECT_ROOT / "quickstart_demo.db"
20
+
21
+
22
+ def run(cmd: list[str], check: bool = True) -> subprocess.CompletedProcess[str]:
23
+ """Run a command and print it."""
24
+ print(f" $ {' '.join(str(c) for c in cmd)}")
25
+ return subprocess.run(cmd, check=check, text=True)
26
+
27
+
28
+ def check_lm_studio() -> bool:
29
+ """Check if LM Studio is running."""
30
+ try:
31
+ with urllib.request.urlopen("http://127.0.0.1:1234/v1/models", timeout=3) as r:
32
+ return r.status == 200
33
+ except OSError:
34
+ return False
35
+
36
+
37
+ def check_ollama() -> bool:
38
+ """Check if Ollama is running."""
39
+ try:
40
+ with urllib.request.urlopen("http://localhost:11434/api/tags", timeout=3) as r:
41
+ return r.status == 200
42
+ except OSError:
43
+ return False
44
+
45
+
46
+ def sqlseed_cmd(python: str) -> list[str]:
47
+ """Build a sqlseed CLI invocation."""
48
+ return [python, "-c", "from sqlseed.cli.main import cli; cli()", "--"]
49
+
50
+
51
+ def _fill_data(python: str) -> None:
52
+ """Fill the demo database with sample data using sqlseed CLI."""
53
+ cmd = sqlseed_cmd(python)
54
+ for table, count in (("users", 500), ("projects", 200), ("orders", 1000)):
55
+ run([*cmd, "fill", str(DB_PATH), "-t", table, "-n", str(count)])
56
+
57
+ print()
58
+ print(" Data fill complete!")
59
+
60
+
61
+ def _run_ai_analysis_step(args: argparse.Namespace, python: str) -> None:
62
+ """Run the Gemma 4 AI schema analysis step."""
63
+ print("[5/5] Gemma 4 AI Schema Analysis...")
64
+ print(f" Backend: {args.backend}")
65
+ print(f" Model: {args.model}")
66
+ print()
67
+
68
+ os.environ["SQLSEED_AI_BACKEND"] = args.backend
69
+ os.environ["SQLSEED_AI_MODEL"] = args.model
70
+
71
+ ai_ok = False
72
+ if args.backend == "lm_studio":
73
+ if check_lm_studio():
74
+ ai_ok = True
75
+ else:
76
+ print(" Skipped: LM Studio is not running")
77
+ print(" Please start LM Studio and load a Gemma 4 model")
78
+ print(" Download: https://lmstudio.ai/")
79
+ elif args.backend == "ollama":
80
+ if check_ollama():
81
+ ai_ok = True
82
+ else:
83
+ print(" Skipped: Ollama is not running")
84
+ print(" Example: ollama pull gemma4:4b")
85
+ elif args.backend == "google":
86
+ if os.environ.get("GOOGLE_API_KEY"):
87
+ ai_ok = True
88
+ else:
89
+ print(" Skipped: GOOGLE_API_KEY not set")
90
+ print(" Example: export GOOGLE_API_KEY=your-key")
91
+
92
+ if ai_ok:
93
+ output_yaml = str(PROJECT_ROOT / "projects_config.yaml")
94
+ cmd = sqlseed_cmd(python)
95
+ run([*cmd, "ai-suggest", str(DB_PATH), "-t", "projects", "-o", output_yaml, "--timeout", "300"])
96
+
97
+
98
+ def main() -> None:
99
+ parser = argparse.ArgumentParser(description="GemmaSQLSeed one-click setup")
100
+ parser.add_argument(
101
+ "--backend",
102
+ choices=["lm_studio", "ollama", "google"],
103
+ default=os.environ.get("SQLSEED_AI_BACKEND", "lm_studio"),
104
+ help="AI backend (default: lm_studio)",
105
+ )
106
+ parser.add_argument(
107
+ "--model",
108
+ default=os.environ.get("SQLSEED_AI_MODEL", "google/gemma-4-e4b"),
109
+ help="Model name (default: google/gemma-4-e4b)",
110
+ )
111
+ parser.add_argument(
112
+ "--skip-install",
113
+ action="store_true",
114
+ help="Skip dependency installation, use current Python environment",
115
+ )
116
+ args = parser.parse_args()
117
+
118
+ print("=" * 50)
119
+ print(" GemmaSQLSeed Quick Start")
120
+ print("=" * 50)
121
+ print()
122
+
123
+ # Determine which python to use
124
+ if args.skip_install:
125
+ # Use current Python (already has sqlseed installed)
126
+ python = sys.executable
127
+ print("[1/5] Using current Python environment (skip-install)")
128
+ print("[2/5] Skipping installation (--skip-install)")
129
+ else:
130
+ # Create venv and install
131
+ venv_path = PROJECT_ROOT / ".venv"
132
+ if not venv_path.exists():
133
+ print("[1/5] Creating virtual environment...")
134
+ run([sys.executable, "-m", "venv", str(venv_path)])
135
+ else:
136
+ print("[1/5] Virtual environment exists, skipping")
137
+
138
+ if sys.platform == "win32":
139
+ python = str(venv_path / "Scripts" / "python.exe")
140
+ else:
141
+ python = str(venv_path / "bin" / "python")
142
+
143
+ print("[2/5] Installing dependencies (may take a few minutes on first run)...")
144
+ run([python, "-m", "pip", "install", "-q", "-e", f"{PROJECT_ROOT}[dev,all]"])
145
+ run([python, "-m", "pip", "install", "-q", "-e", str(PROJECT_ROOT / "plugins" / "sqlseed-ai")])
146
+ run([python, "-m", "pip", "install", "-q", "-e", str(PROJECT_ROOT / "plugins" / "mcp-server-sqlseed")])
147
+
148
+ # ── Step 3: Create test database ─────────────────────────────────
149
+ print("[3/5] Creating test database...")
150
+ if DB_PATH.exists():
151
+ DB_PATH.unlink()
152
+
153
+ create_db_script = Path(__file__).parent / "_create_demo_db.py"
154
+ run([python, str(create_db_script), str(DB_PATH)])
155
+
156
+ # ── Step 4: Fill data ────────────────────────────────────────────
157
+ print("[4/5] Filling data (zero-config)...")
158
+ _fill_data(python)
159
+
160
+ # ── Step 5: Gemma 4 AI analysis ──────────────────────────────────
161
+ _run_ai_analysis_step(args, python)
162
+
163
+ # ── Done ─────────────────────────────────────────────────────────
164
+ print()
165
+ print("=" * 50)
166
+ print(" Setup Complete!")
167
+ print("=" * 50)
168
+ print()
169
+ print(f" Database: {DB_PATH}")
170
+ cli_call = 'python -c "from sqlseed.cli.main import cli; cli()" --'
171
+ print(f" Preview: {cli_call} preview {DB_PATH} -t users -n 5")
172
+ print(f" Inspect: {cli_call} inspect {DB_PATH} --show-mapping")
173
+ print(f" AI Suggest: {cli_call} ai-suggest {DB_PATH} -t users -o config.yaml")
174
+ print(" MCP Server: mcp-server-sqlseed")
175
+ print()
176
+
177
+
178
+ if __name__ == "__main__":
179
+ main()
@@ -475,15 +475,19 @@ def ai_suggest(
475
475
  ai_config = AIConfig.from_env().apply_overrides(api_key=api_key, base_url=base_url, model=model)
476
476
  ai_config.timeout = timeout
477
477
 
478
- if not ai_config.api_key:
478
+ if not ai_config.resolve_api_key():
479
479
  click.echo(
480
- "Error: AI API key not configured. Set SQLSEED_AI_API_KEY or OPENAI_API_KEY, or use --api-key.",
480
+ "Error: AI API key not configured. "
481
+ "Set SQLSEED_AI_API_KEY or OPENAI_API_KEY. "
482
+ "For Google AI Studio, set GOOGLE_API_KEY. "
483
+ "For LM Studio/Ollama, set SQLSEED_AI_BACKEND=lm_studio or ollama.",
481
484
  err=True,
482
485
  )
483
486
  raise SystemExit(1)
484
487
 
485
488
  resolved_model = ai_config.resolve_model()
486
- click.echo(f"Using AI model: {resolved_model} (via OpenRouter)")
489
+ backend_name = ai_config.backend.value.replace("_", " ").title()
490
+ click.echo(f"Using AI model: {resolved_model} (via {backend_name})")
487
491
 
488
492
  analyzer = SchemaAnalyzer(config=ai_config)
489
493
  total_timeout = timeout * 2
@@ -491,13 +495,15 @@ def ai_suggest(
491
495
  old_handler: Any = None
492
496
  if hasattr(signal, "SIGALRM"):
493
497
  old_handler = signal.signal(signal.SIGALRM, lambda _s, _f: _sigalrm_handler(total_timeout))
494
- signal.alarm(int(total_timeout))
498
+ _alarm_fn = vars(signal)["alarm"]
499
+ _alarm_fn(int(total_timeout))
495
500
 
496
501
  try:
497
502
  result = _run_ai_analysis(analyzer, db_path, table, verify, max_retries, no_cache)
498
503
  finally:
499
504
  if hasattr(signal, "SIGALRM"):
500
- signal.alarm(0)
505
+ _alarm_fn = vars(signal)["alarm"]
506
+ _alarm_fn(0)
501
507
  if old_handler is not None:
502
508
  signal.signal(signal.SIGALRM, old_handler)
503
509
 
@@ -1346,7 +1346,6 @@ dependencies = [
1346
1346
  { name = "rich" },
1347
1347
  { name = "rstr" },
1348
1348
  { name = "simpleeval" },
1349
- { name = "sqlite-utils" },
1350
1349
  { name = "structlog" },
1351
1350
  { name = "typing-extensions" },
1352
1351
  ]
@@ -1355,6 +1354,7 @@ dependencies = [
1355
1354
  all = [
1356
1355
  { name = "faker" },
1357
1356
  { name = "mimesis" },
1357
+ { name = "sqlite-utils" },
1358
1358
  { name = "tqdm" },
1359
1359
  ]
1360
1360
  dev = [
@@ -1365,6 +1365,7 @@ dev = [
1365
1365
  { name = "pytest-benchmark" },
1366
1366
  { name = "pytest-cov" },
1367
1367
  { name = "ruff" },
1368
+ { name = "sqlite-utils" },
1368
1369
  { name = "tqdm" },
1369
1370
  ]
1370
1371
  docs = [
@@ -1377,7 +1378,10 @@ faker = [
1377
1378
  mimesis = [
1378
1379
  { name = "mimesis" },
1379
1380
  ]
1380
- notebook = [
1381
+ sqlite-utils = [
1382
+ { name = "sqlite-utils" },
1383
+ ]
1384
+ tqdm = [
1381
1385
  { name = "tqdm" },
1382
1386
  ]
1383
1387
 
@@ -1403,14 +1407,16 @@ requires-dist = [
1403
1407
  { name = "rstr", specifier = ">=3.2" },
1404
1408
  { name = "ruff", marker = "extra == 'dev'", specifier = ">=0.5" },
1405
1409
  { name = "simpleeval", specifier = ">=1.0" },
1406
- { name = "sqlite-utils", specifier = ">=3.36" },
1410
+ { name = "sqlite-utils", marker = "extra == 'all'", specifier = ">=3.36" },
1411
+ { name = "sqlite-utils", marker = "extra == 'dev'", specifier = ">=3.36" },
1412
+ { name = "sqlite-utils", marker = "extra == 'sqlite-utils'", specifier = ">=3.36" },
1407
1413
  { name = "structlog", specifier = ">=24.0" },
1408
1414
  { name = "tqdm", marker = "extra == 'all'", specifier = ">=4.66" },
1409
1415
  { name = "tqdm", marker = "extra == 'dev'", specifier = ">=4.66" },
1410
- { name = "tqdm", marker = "extra == 'notebook'", specifier = ">=4.66" },
1416
+ { name = "tqdm", marker = "extra == 'tqdm'", specifier = ">=4.66" },
1411
1417
  { name = "typing-extensions", specifier = ">=4.4" },
1412
1418
  ]
1413
- provides-extras = ["all", "dev", "docs", "faker", "mimesis", "notebook"]
1419
+ provides-extras = ["all", "dev", "docs", "faker", "mimesis", "sqlite-utils", "tqdm"]
1414
1420
 
1415
1421
  [[package]]
1416
1422
  name = "structlog"
File without changes
File without changes
File without changes
File without changes