A powerful tool that uses LangChain + GigaChat to extract sourceβtoβtarget lineage from SQL statements and automatically optimise the extraction prompt via reflexion agents (singleβquery and batch).
The project includes a Streamlit web interface for interactive exploration and batch processing.
- Singleβquery lineage extraction β get target table and source tables as JSON + graph.
- Batch processing β upload multiple
.sql/.txtfiles (each may contain several statements, split by;). - Tableβcentric view β enter a table name to see all queries where it is target or source, plus a dependency graph.
- Prompt optimisation agents
- Singleβquery agent (
GigaChatSQLLineageAgent): iteratively improves a prompt for one SQL using a reflexion loop (F1βscore guided). - Batch agent (
GigaChatBatchSQLLineageAgent): optimises a single prompt to work well across multiple SQL statements simultaneously, aggregating metrics and using a batchβaware reflection prompt.
- Singleβquery agent (
- LangChain GigaChat integration β uses
langchain_gigachatfor both extraction and reflection. - All outputs saved β optimisation history (prompts, validation results) can be written to JSON.
git clone <your-repo-url>
cd sql-lineage-toolWe recommend using uv (fast Python package installer) or plain pip:
# Using uv
uv venv
source .venv/bin/activate # macOS/Linux
# or .venv\Scripts\activate # Windows
uv pip install -e .
# Using pip
python -m venv .venv
source .venv/bin/activate
pip install -e .Create a .env file in the project root:
GIGACHAT_CREDENTIALS=your_gigachat_api_key_hereOr export it as an environment variable:
export GIGACHAT_CREDENTIALS=your_gigachat_api_key_hereOptionally, you can also set GIGACHAT_SCOPE and GIGACHAT_BASE_URL if needed.
The main entry point for interactive use is Web/app.py.
streamlit run Web/app.pyThe app will open in your browser at http://localhost:8501.
- Left sidebar: configure GigaChat model (
GigaChat,GigaChat-Pro,GigaChat-Max), credentials, temperature, max tokens, etc. - Two main tabs:
- Single Query Lineage β paste one SQL, get JSON + graph.
- Table Lineage (Batch) β upload files, see an overview, click a target to explore.
The project is structured into several classes, each with a clear responsibility. Below is a simplified diagram for the GigaChat version:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Streamlit Frontend β
β (Web/app.py) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β SQLLineageExtractor β
β (langchain_gigachat.GigaChat) β
β - prompt template (contains {sql_text} & {format_instructions})β
β - extract(sql) β {"target": ..., "sources": ...} β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β SQLLineageValidator β
β (from validation_classes) β
β - run_comprehensive_validation(extractor, sql, expected) β
β β returns {"status": "SUCCESS"/"FAILED", "metrics": {...}} β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β GigaChatSQLLineageAgent β
β (singleβquery prompt optimisation) β
β - owns an extractor (for lineage extraction) β
β - owns a separate GigaChat LLM (for reflection) β
β - create_workflow() β LangGraph with validate + reflect nodes β
β - optimize_prompt() β best prompt & F1 history β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β GigaChatBatchSQLLineageAgent β
β (batch prompt optimisation) β
β - validates a prompt against multiple SQLs in parallel β
β - aggregates F1 scores, min F1, success rate β
β - batchβaware reflection prompt β
β - stops when average F1 == 1.0 β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- Wraps
GigaChatfromlangchain_gigachat. - Its prompt template is the prompt being optimised.
- Provides the
extract()method used by both the app and the agents.
- Compares the extractorβs output against a groundβtruth result.
- Returns F1 score, precision, recall β metrics that the agent uses to decide if the prompt is good enough.
- Reuses the same
SQLLineageExtractor(or creates one) to perform extraction during optimisation. - Maintains its own
GigaChatinstance (with identical parameters) to generate improved prompts. - Implements a reflexion loop as a LangGraph workflow:
validate_node: runs extraction + validation, records F1.reflect_node: feeds errors and current prompt to the chat model β produces a refined prompt.
- Stops when F1 = 1.0 or max iterations reached.
- Inherits from the singleβquery agent but overrides
validate_batchand the reflection prompt. - Processes all SQLs in parallel with a concurrency limit (
max_concurrent). - Aggregates metrics (average F1, min F1, success rate) to decide when to stop.
- The reflection prompt receives a summary of all validation results and must propose a prompt that works for the whole batch.
- Instantiates
SQLLineageExtractor(cached) with GigaChat parameters. - For the batch tab, stores every extracted statement together with its full SQL and lineage.
- When a user clicks a target table, the lookup input is populated and the downstream/upstream graph is drawn.
- The app does not directly use the agents β they are meant for offline prompt optimisation.
This modular design keeps the interactive web interface separate from the promptβoptimisation logic, making both parts easier to maintain and extend.
from Classes.model_classes import SQLLineageExtractor
from Classes.prompt_refiner import GigaChatSQLLineageAgent
import os
# Create extractor
extractor = SQLLineageExtractor(
credentials=os.environ["GIGACHAT_CREDENTIALS"],
model="GigaChat-Pro",
temperature=0.1,
max_tokens=1024
)
# Create agent, passing the extractor (so they share the same model)
agent = GigaChatSQLLineageAgent(
credentials=os.environ["GIGACHAT_CREDENTIALS"],
model="GigaChat-Pro",
extractor=extractor,
max_iterations=5
)
# Ground truth (what the correct lineage should be)
expected = {
"target": "analytics.sales_summary",
"sources": ["products.raw_data", "sales.transactions"]
}
# Run optimisation
result = agent.optimize_prompt_sync(
sql="INSERT INTO analytics.sales_summary SELECT p.category, SUM(s.amount) FROM products.raw_data p JOIN sales.transactions s ON p.id = s.product_id",
expected_result=expected,
output_file="optimisation_log.json",
verbose=True
)
print("Best prompt:\n", result["optimized_prompt"])
print("F1 score:", result["f1_score"])from Classes.model_classes import SQLLineageExtractor
from Classes.prompt_refiner import GigaChatBatchSQLLineageAgent
extractor = SQLLineageExtractor(credentials="...", model="GigaChat")
agent = GigaChatBatchSQLLineageAgent(
credentials="...",
model="GigaChat",
extractor=extractor,
max_concurrent=3, # limit simultaneous calls
max_iterations=5
)
sqls = [
"INSERT INTO schema1.table1 SELECT ...",
"UPDATE schema2.table2 SET ..."
]
expected = [
{"target": "schema1.table1", "sources": ["source1"]},
{"target": "schema2.table2", "sources": ["source2"]}
]
result = await agent.optimize_prompt_batch(
sqls=sqls,
expected_results=expected,
output_file="batch_optimisation.json",
verbose=True
)
print("Best batch prompt:", result["optimized_prompt"])
print("Average F1:", result["best_avg_f1"])This workflow guides you through using the Table Lineage (Batch) tab of the web interface to explore lineage across multiple SQL scripts.
- You have started the app with
streamlit run Web/app.py - Your GigaChat credentials are entered in the sidebar (or set in
.env)
-
Open the βTable Lineage (Batch)β tab
Click the second tab at the top of the page. -
Upload one or more SQL files
- Drag & drop
.sqlor.txtfiles into the file uploader, or click βBrowse filesβ. - Files may contain multiple SQL statements separated by semicolons (
;). - Example file content:
INSERT INTO target1 SELECT * FROM source1; INSERT INTO target2 SELECT * FROM source2;
- Drag & drop
-
Processing
The app will:- Split each file into individual statements.
- Run lineage extraction on each statement using the
SQLLineageExtractor. - Display a progress bar and show any errors per statement.
- Store results in the session.
-
View the extracted lineage overview
After processing, youβll see a table with:- File name
- Statement number
- Target table (clickable button)
- Sources count
-
Click on a target table
- Clicking any target button automatically fills the βLook up a tableβ input field.
- The page scrolls to the lookup section and displays:
- How many times the table appears as Target and as Source.
- Expandable sections listing every occurrence.
-
Explore occurrences
- As Target: For each occurrence you see the source tables and the full SQL in a code block (with a copy button).
- As Source: For each occurrence you see the target table and the full SQL.
-
Visualise the lineage graph
Below the occurrence lists, an interactive Graphviz graph shows:- Upstream sources (tables that feed into the selected table) on the left.
- Downstream targets (tables that use the selected table as a source) on the right.
- The central node is your selected table.
-
Copy any SQL
- Every displayed SQL code block has a copy icon in the topβright corner β click it to copy the entire statement to your clipboard.
-
Clear the session
- Use the βClear all stored lineage resultsβ button at the bottom to reset and start fresh.
This diagram shows the steps a user takes when using the Streamlit web interface, from loading the app to exploring lineage results.
- The Single Query Lineage tab works the same way, but only for one SQL at a time β youβll get immediate JSON and a graph.
- If you have many statements, the graph limits nodes to 15 for readability, with a
β¦indicator if more exist. - The app caches the extractor, so repeated lookups are fast.
| Issue | Solution |
|---|---|
ModuleNotFoundError (e.g., langchain_gigachat) |
Install the missing package: pip install langchain-gigachat. |
| Graphviz not rendering | Install system Graphviz: sudo apt install graphviz (Ubuntu), brew install graphviz (macOS), or download from graphviz.org (Windows). |
GIGACHAT_CREDENTIALS errors |
Ensure credentials are set in .env or as environment variable. |
streamlit: command not found |
Install Streamlit: pip install streamlit or add it to your dependencies. |
| Model fails to load | Verify model name (GigaChat, GigaChat-Pro, GigaChat-Max) and that your credentials have access to it. |
| App is slow | Reduce max_tokens or max_concurrent (in the batch agent). First extraction may be slower due to model loading. |
| Agent returns empty results after reflection | Check that the refined prompt contains {sql_text} and {format_instructions} β the agent automatically adds them if missing. |



