Skip to content

Commit 78b9309

Browse files
Complete code merge into Main Branch
1 parent 695a866 commit 78b9309

File tree

20 files changed

+1289
-0
lines changed

20 files changed

+1289
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# This workflow will run integration tests for the current project once per day
2+
3+
name: Integration Tests
4+
5+
on:
6+
schedule:
7+
- cron: "37 14 * * *" # Run at 7:37 AM Pacific Time (14:37 UTC) every day
8+
workflow_dispatch: # Allows triggering the workflow manually in GitHub UI
9+
10+
# If another scheduled run starts while this workflow is still running,
11+
# cancel the earlier run in favor of the next run.
12+
concurrency:
13+
group: ${{ github.workflow }}-${{ github.ref }}
14+
cancel-in-progress: true
15+
16+
jobs:
17+
integration-tests:
18+
name: Integration Tests
19+
strategy:
20+
matrix:
21+
os: [ubuntu-latest]
22+
python-version: ["3.11", "3.12"]
23+
runs-on: ${{ matrix.os }}
24+
services:
25+
elasticsearch:
26+
image: elasticsearch:8.13.0
27+
env:
28+
discovery.type: single-node
29+
xpack.license.self_generated.type: trial
30+
xpack.security.enabled: false # disable password and TLS; never do this in production!
31+
ports:
32+
- 9200:9200
33+
options: >-
34+
--health-cmd "curl --fail http://localhost:9200/_cluster/health"
35+
--health-start-period 10s
36+
--health-timeout 3s
37+
--health-interval 3s
38+
--health-retries 10
39+
steps:
40+
- uses: actions/checkout@v4
41+
- name: Set up Python ${{ matrix.python-version }}
42+
uses: actions/setup-python@v4
43+
with:
44+
python-version: ${{ matrix.python-version }}
45+
- name: Install dependencies
46+
run: |
47+
curl -LsSf https://astral.sh/uv/install.sh | sh
48+
uv venv
49+
uv pip install -r pyproject.toml
50+
uv pip install -U pytest-asyncio
51+
- name: Run integration tests
52+
env:
53+
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
54+
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
55+
ELASTICSEARCH_URL: http://localhost:9200
56+
ELASTICSEARCH_USER: elastic
57+
ELASTICSEARCH_PASSWORD: ""
58+
LANGSMITH_API_KEY: ${{ secrets.LANGSMITH_API_KEY }}
59+
LANGSMITH_TRACING: true
60+
run: |
61+
uv run pytest tests/integration_tests
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# This workflow will run unit tests for the current project
2+
3+
name: CI
4+
5+
on:
6+
push:
7+
branches: ["main"]
8+
pull_request:
9+
workflow_dispatch: # Allows triggering the workflow manually in GitHub UI
10+
11+
# If another push to the same PR or branch happens while this workflow is still running,
12+
# cancel the earlier run in favor of the next run.
13+
concurrency:
14+
group: ${{ github.workflow }}-${{ github.ref }}
15+
cancel-in-progress: true
16+
17+
jobs:
18+
unit-tests:
19+
name: Unit Tests
20+
strategy:
21+
matrix:
22+
os: [ubuntu-latest]
23+
python-version: ["3.11", "3.12"]
24+
runs-on: ${{ matrix.os }}
25+
steps:
26+
- uses: actions/checkout@v4
27+
- name: Set up Python ${{ matrix.python-version }}
28+
uses: actions/setup-python@v4
29+
with:
30+
python-version: ${{ matrix.python-version }}
31+
- name: Install dependencies
32+
run: |
33+
curl -LsSf https://astral.sh/uv/install.sh | sh
34+
uv venv
35+
uv pip install -r pyproject.toml
36+
- name: Lint with ruff
37+
run: |
38+
uv pip install ruff
39+
uv run ruff check .
40+
- name: Lint with mypy
41+
run: |
42+
uv pip install mypy
43+
uv run mypy --strict src/
44+
- name: Check README spelling
45+
uses: codespell-project/actions-codespell@v2
46+
with:
47+
ignore_words_file: .codespellignore
48+
path: README.md
49+
- name: Check code spelling
50+
uses: codespell-project/actions-codespell@v2
51+
with:
52+
ignore_words_file: .codespellignore
53+
path: src/
54+
- name: Run tests with pytest
55+
run: |
56+
uv pip install pytest
57+
uv run pytest tests/unit_tests
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2024 LangChain
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
.PHONY: all format lint test tests test_watch integration_tests docker_tests help extended_tests
2+
3+
# Default target executed when no arguments are given to make.
4+
all: help
5+
6+
# Define a variable for the test file path.
7+
TEST_FILE ?= tests/unit_tests/
8+
9+
test:
10+
python -m pytest $(TEST_FILE)
11+
12+
test_watch:
13+
python -m ptw --snapshot-update --now . -- -vv tests/unit_tests
14+
15+
test_profile:
16+
python -m pytest -vv tests/unit_tests/ --profile-svg
17+
18+
extended_tests:
19+
python -m pytest --only-extended $(TEST_FILE)
20+
21+
22+
######################
23+
# LINTING AND FORMATTING
24+
######################
25+
26+
# Define a variable for Python and notebook files.
27+
PYTHON_FILES=src/
28+
MYPY_CACHE=.mypy_cache
29+
lint format: PYTHON_FILES=.
30+
lint_diff format_diff: PYTHON_FILES=$(shell git diff --name-only --diff-filter=d main | grep -E '\.py$$|\.ipynb$$')
31+
lint_package: PYTHON_FILES=src
32+
lint_tests: PYTHON_FILES=tests
33+
lint_tests: MYPY_CACHE=.mypy_cache_test
34+
35+
lint lint_diff lint_package lint_tests:
36+
python -m ruff check .
37+
[ "$(PYTHON_FILES)" = "" ] || python -m ruff format $(PYTHON_FILES) --diff
38+
[ "$(PYTHON_FILES)" = "" ] || python -m ruff check --select I $(PYTHON_FILES)
39+
[ "$(PYTHON_FILES)" = "" ] || python -m mypy --strict $(PYTHON_FILES)
40+
[ "$(PYTHON_FILES)" = "" ] || mkdir -p $(MYPY_CACHE) && python -m mypy --strict $(PYTHON_FILES) --cache-dir $(MYPY_CACHE)
41+
42+
format format_diff:
43+
ruff format $(PYTHON_FILES)
44+
ruff check --select I --fix $(PYTHON_FILES)
45+
46+
spell_check:
47+
codespell --toml pyproject.toml
48+
49+
spell_fix:
50+
codespell --toml pyproject.toml -w
51+
52+
######################
53+
# HELP
54+
######################
55+
56+
help:
57+
@echo '----'
58+
@echo 'format - run code formatters'
59+
@echo 'lint - run linters'
60+
@echo 'test - run unit tests'
61+
@echo 'tests - run unit tests'
62+
@echo 'test TEST_FILE=<test_file> - run all tests in file'
63+
@echo 'test_watch - run unit tests in watch mode'
64+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
2+
# LangGraph RAG Workflow with Elasticsearch
3+
4+
This project contains the code to create a custom agent using the LangGraph Retrieval Agent Template with Elasticsearch to build an efficient Retrieval-Augmented Generation (RAG) workflow for AI-driven responses.
5+
6+
7+
## Introduction
8+
9+
LangGraph, developed by LangChain, simplifies the creation of retrieval-based question-answering systems. By using LangGraph Studio and LangGraph CLI, you can quickly build agents that index and retrieve documents using Elasticsearch.
10+
11+
## Prerequisites
12+
13+
Before you start, ensure you have the following installed:
14+
15+
- Elasticsearch (Cloud or on-prem, version 8.0.0 or higher)
16+
- Python 3.9+
17+
- Access to an LLM provider like Cohere, OpenAI, or Anthropic
18+
19+
## Steps to Set Up the LangGraph App
20+
21+
### 1. Install LangGraph CLI
22+
23+
```bash
24+
pip install --upgrade "langgraph-cli[inmem]"
25+
```
26+
### 2. Create LangGraph App
27+
```
28+
mkdir lg-agent-demo
29+
cd lg-agent-demo
30+
langgraph new lg-agent-demo
31+
```
32+
### 3. Install Dependencies
33+
Create a virtual environment and install the dependencies:
34+
35+
For macOS:
36+
```
37+
python3 -m venv lg-demo
38+
source lg-demo/bin/activate
39+
pip install -e .
40+
```
41+
For Windows:
42+
```
43+
python3 -m venv lg-demo
44+
lg-demo\Scripts\activate
45+
pip install -e .
46+
```
47+
### 4. Set Up Environment
48+
Create a .env file by copying the example:
49+
50+
```
51+
cp .env.example .env
52+
```
53+
Then, configure your .env file with your API keys and URLs for Elasticsearch and LLM.
54+
55+
### 5. Update configuration.py
56+
Modify the configuration.py file to set up your LLM models, like Cohere (or OpenAI/Anthropic), as shown below:
57+
58+
59+
```embedding_model = "cohere/embed-english-v3.0"
60+
response_model = "cohere/command-r-08-2024"
61+
query_model = "cohere/command-r-08-2024"
62+
```
63+
64+
## Running the Agent
65+
66+
### 1. Launch LangGraph Server
67+
```
68+
cd lg-agent-demo
69+
langgraph dev
70+
```
71+
This starts the LangGraph API server locally.
72+
73+
### 2. Open LangGraph Studio
74+
You can now access the LangGraph Studio UI and see the following:
75+
<img width="1306" alt="Screenshot 2025-04-01 at 6 02 31 PM" src="https://github.com/user-attachments/assets/c7c13645-99a1-48b2-8d3c-c1135fd33f54" />
76+
Indexer Graph: Indexes documents into Elasticsearch.
77+
78+
<img width="776" alt="Screenshot 2025-03-11 at 6 08 09 PM" src="https://github.com/user-attachments/assets/5d61b9d0-ae9e-4d66-9e99-fa27bce7a1d0" />
79+
80+
81+
Retrieval Graph: Retrieves data from Elasticsearch and answers queries using the LLM.
82+
83+
### 3. Index Sample Documents
84+
Index the sample documents into Elasticsearch (representing the NoveTech Solutions reports).
85+
86+
### 4. Run the Retrieval Graph
87+
Enter a query like:
88+
89+
```
90+
What was NovaTech Solutions' total revenue in Q1 2025?
91+
The system will retrieve relevant documents and provide an answer.
92+
```
93+
## Customizing the Retrieval Agent
94+
## Query Prediction
95+
To enhance user experience, add a query prediction feature based on the context from previous queries and retrieved documents. Here’s what to do:
96+
97+
1. Add predict_query function in graph.py.
98+
99+
2. Modify the respond function to return a response object.
100+
101+
3. Update the graph structure to include a new node for query prediction.
102+
103+
4. Modify Prompts and Configuration
104+
Update prompts.py to define a prompt for predicting the next question. Then, modify configuration.py to add this new prompt.
105+
106+
```
107+
predict_next_question_prompt: str = "Your prompt here"
108+
```
109+
Re-run the Retrieval Graph
110+
Run the query again to see the predicted next three questions based on the context.
111+
<img width="732" alt="Screenshot 2025-03-17 at 3 06 54 PM" src="https://github.com/user-attachments/assets/88832fa6-4dc9-41cc-894d-d3d437bf4d80" />
112+
113+
## Conclusion
114+
By using the LangGraph Retrieval Agent template with Elasticsearch, you can:
115+
116+
- Accelerate development by using pre-configured templates.
117+
118+
- Easily deploy with built-in API support and scaling.
119+
120+
- Customize workflows to fit your specific use case.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"dependencies": ["."],
3+
"graphs": {
4+
"indexer": "./src/retrieval_graph/index_graph.py:graph",
5+
"retrieval_graph": "./src/retrieval_graph/graph.py:graph"
6+
},
7+
"env": ".env"
8+
}

0 commit comments

Comments
 (0)