langchain-gmi 0.1.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.
- langchain_gmi-0.1.0/.github/workflows/ci.yml +30 -0
- langchain_gmi-0.1.0/.gitignore +16 -0
- langchain_gmi-0.1.0/CHANGELOG.md +15 -0
- langchain_gmi-0.1.0/LICENSE +21 -0
- langchain_gmi-0.1.0/PKG-INFO +236 -0
- langchain_gmi-0.1.0/README.md +203 -0
- langchain_gmi-0.1.0/docs/live-validation.md +21 -0
- langchain_gmi-0.1.0/examples/01_basic_chat.py +26 -0
- langchain_gmi-0.1.0/examples/02_agent_with_tools.py +109 -0
- langchain_gmi-0.1.0/examples/03_structured_output.py +29 -0
- langchain_gmi-0.1.0/langchain_gmi/__init__.py +8 -0
- langchain_gmi-0.1.0/langchain_gmi/chat_models.py +76 -0
- langchain_gmi-0.1.0/langchain_gmi/models.py +47 -0
- langchain_gmi-0.1.0/langchain_gmi/py.typed +0 -0
- langchain_gmi-0.1.0/langchain_gmi/utils.py +55 -0
- langchain_gmi-0.1.0/pyproject.toml +57 -0
- langchain_gmi-0.1.0/tests/__init__.py +0 -0
- langchain_gmi-0.1.0/tests/conftest.py +35 -0
- langchain_gmi-0.1.0/tests/test_chat_models.py +401 -0
- langchain_gmi-0.1.0/tests/test_examples.py +94 -0
- langchain_gmi-0.1.0/tests/test_model_aliases.py +70 -0
- langchain_gmi-0.1.0/tests/test_utils.py +170 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on: [push, pull_request]
|
|
4
|
+
|
|
5
|
+
jobs:
|
|
6
|
+
test:
|
|
7
|
+
runs-on: ubuntu-latest
|
|
8
|
+
strategy:
|
|
9
|
+
fail-fast: false
|
|
10
|
+
matrix:
|
|
11
|
+
python: ["3.10", "3.11", "3.12", "3.13"]
|
|
12
|
+
dependencies: [latest]
|
|
13
|
+
include:
|
|
14
|
+
- python: "3.10"
|
|
15
|
+
dependencies: minimum
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
- uses: actions/setup-python@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: ${{ matrix.python }}
|
|
21
|
+
- run: python -m pip install -e ".[dev]"
|
|
22
|
+
- if: matrix.dependencies == 'minimum'
|
|
23
|
+
run: >-
|
|
24
|
+
python -m pip install
|
|
25
|
+
langchain-openai==0.2.0 langchain-core==0.3.0
|
|
26
|
+
httpx==0.27.0 openai==1.40.0 pydantic==2.5.2
|
|
27
|
+
- run: ruff check .
|
|
28
|
+
- run: ruff format --check .
|
|
29
|
+
- run: pytest
|
|
30
|
+
- run: python -m build
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0 - 2026-11-14
|
|
4
|
+
|
|
5
|
+
Initial release of the community LangChain integration for GMI Cloud.
|
|
6
|
+
|
|
7
|
+
- `ChatGMI` with GMI authentication and endpoint defaults.
|
|
8
|
+
- Six convenience model aliases and arbitrary raw model IDs.
|
|
9
|
+
- Sync and async chat and streaming through Chat Completions.
|
|
10
|
+
- OpenAI-style tool calling and Pydantic structured output.
|
|
11
|
+
- Provider metadata for LangChain runs.
|
|
12
|
+
- `list_gmi_models` with API metadata and normalized context lengths.
|
|
13
|
+
- Offline tests, examples, MIT license, and CI configuration.
|
|
14
|
+
|
|
15
|
+
Live functional checks passed with `deepseek-ai/deepseek-v4.1-flash-1017`.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 langchain-gmi contributors
|
|
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.
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: langchain-gmi
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: LangChain chat models for GMI Cloud's OpenAI-compatible Inference Engine
|
|
5
|
+
Project-URL: Homepage, https://github.com/dhruvil-codes/langchain-gmi
|
|
6
|
+
Project-URL: Documentation, https://github.com/dhruvil-codes/langchain-gmi#readme
|
|
7
|
+
Project-URL: Repository, https://github.com/dhruvil-codes/langchain-gmi
|
|
8
|
+
Project-URL: Issues, https://github.com/dhruvil-codes/langchain-gmi/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/dhruvil-codes/langchain-gmi/blob/main/CHANGELOG.md
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: gmi,inference,langchain,llm
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Typing :: Typed
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Requires-Dist: httpx<1.0,>=0.27.0
|
|
23
|
+
Requires-Dist: langchain-core<2.0.0,>=0.3.0
|
|
24
|
+
Requires-Dist: langchain-openai<2.0.0,>=0.2.0
|
|
25
|
+
Requires-Dist: pydantic<3.0,>=2.0
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: build>=1.2; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
30
|
+
Requires-Dist: ruff>=0.9; extra == 'dev'
|
|
31
|
+
Requires-Dist: twine>=6; extra == 'dev'
|
|
32
|
+
Description-Content-Type: text/markdown
|
|
33
|
+
|
|
34
|
+
# langchain-gmi
|
|
35
|
+
|
|
36
|
+
[](https://www.gmicloud.ai/en/developers) [](https://www.python.org/)
|
|
37
|
+
|
|
38
|
+
LangChain integration for GMI Cloud's OpenAI-compatible Inference Engine. Access DeepSeek V3.2, Claude Sonnet 4.5, and open models through one endpoint, alongside GMI Cloud's NVIDIA H100 GPU inference infrastructure. This is a community integration.
|
|
39
|
+
|
|
40
|
+
## Install
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pip install langchain-gmi
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Set an API key in your environment:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
export GMI_API_KEY="your-gmi-api-key"
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
PowerShell:
|
|
53
|
+
|
|
54
|
+
```powershell
|
|
55
|
+
$env:GMI_API_KEY = "your-gmi-api-key"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Requires Python 3.10 or newer. The default endpoint is `https://api.gmi-serving.com/v1`. The integration accepts `gmi_api_key`, `api_key`, or `openai_api_key`; `GMI_API_KEY` is the environment variable fallback. Explicit credentials take precedence. Missing or empty credentials raise `ValueError` during construction. `OPENAI_API_KEY` and OpenAI endpoint environment variables are not used to configure this provider.
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
llm = ChatGMI(
|
|
62
|
+
model="deepseek-v3.2",
|
|
63
|
+
# gmi_api_key=secret_from_your_secret_manager,
|
|
64
|
+
base_url="https://api.gmi-serving.com/v1",
|
|
65
|
+
timeout=60,
|
|
66
|
+
max_retries=2,
|
|
67
|
+
metadata={"application": "support"},
|
|
68
|
+
)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Runs include `provider="gmi-cloud"` metadata and `ls_provider="gmi-cloud"` for tracing. API keys use Pydantic secret fields and are excluded from provider-specific exports.
|
|
72
|
+
|
|
73
|
+
## Quickstart
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
from langchain_gmi import ChatGMI
|
|
77
|
+
|
|
78
|
+
llm = ChatGMI(model="deepseek-v3.2")
|
|
79
|
+
response = llm.invoke("What makes GMI Cloud H100 clusters fast?")
|
|
80
|
+
print(response.content)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
`ChatGMI` inherits LangChain's chat model methods, including `invoke`/`ainvoke`, `stream`/`astream`, `bind_tools`, and `with_structured_output`. Availability and behavior of model capabilities depend on the selected model and the API's current support.
|
|
84
|
+
|
|
85
|
+
## Async and streaming
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
import asyncio
|
|
89
|
+
|
|
90
|
+
from langchain_gmi import ChatGMI
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
async def main() -> None:
|
|
94
|
+
llm = ChatGMI(model="deepseek-v3.2")
|
|
95
|
+
|
|
96
|
+
response = await llm.ainvoke("Give me a one-sentence summary of inference APIs.")
|
|
97
|
+
print(response.content)
|
|
98
|
+
|
|
99
|
+
async for chunk in llm.astream("Count from one to three."):
|
|
100
|
+
print(chunk.content, end="", flush=True)
|
|
101
|
+
print()
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
if __name__ == "__main__":
|
|
105
|
+
asyncio.run(main())
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
For synchronous streaming:
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
for chunk in llm.stream("Count from one to three."):
|
|
112
|
+
print(chunk.content, end="", flush=True)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
If your selected model supports usage reporting, pass `stream_options={"include_usage": True}` to `stream` or `astream` and inspect the final chunk's `usage_metadata`. Streaming usage requests are opt-in for this endpoint. Recent `langchain-openai` versions also accept `stream_usage=True`.
|
|
116
|
+
|
|
117
|
+
## Tool calling
|
|
118
|
+
|
|
119
|
+
Bind LangChain tools to the model, then invoke it with a message. The model may return tool calls in `AIMessage.tool_calls`; your application is responsible for executing them and returning the results.
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
from langchain_core.tools import tool
|
|
123
|
+
|
|
124
|
+
from langchain_gmi import ChatGMI
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
@tool
|
|
128
|
+
def multiply(a: int, b: int) -> int:
|
|
129
|
+
"""Multiply two integers."""
|
|
130
|
+
return a * b
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
llm = ChatGMI(model="deepseek-v3.2").bind_tools([multiply])
|
|
134
|
+
message = llm.invoke("What is 6 times 7?")
|
|
135
|
+
print(message.tool_calls)
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
See [`examples/02_agent_with_tools.py`](https://github.com/dhruvil-codes/langchain-gmi/blob/main/examples/02_agent_with_tools.py) for a bounded tool loop with calculator and web search tools.
|
|
139
|
+
|
|
140
|
+
## Structured output
|
|
141
|
+
|
|
142
|
+
Use a Pydantic model to validate extracted fields:
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
from pydantic import BaseModel, Field
|
|
146
|
+
|
|
147
|
+
from langchain_gmi import ChatGMI
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
class SupportTicket(BaseModel):
|
|
151
|
+
"""Fields extracted from a short support request."""
|
|
152
|
+
|
|
153
|
+
category: str = Field(description="Short issue category")
|
|
154
|
+
urgency: int = Field(ge=1, le=5, description="Urgency from 1 (low) to 5 (high)")
|
|
155
|
+
summary: str
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
extract = ChatGMI(model="deepseek-v3.2").with_structured_output(SupportTicket)
|
|
159
|
+
ticket = extract.invoke("My account is locked and our team is blocked from a deadline.")
|
|
160
|
+
print(ticket)
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
The integration's default structured-output strategy is `function_calling`. See [`examples/03_structured_output.py`](https://github.com/dhruvil-codes/langchain-gmi/blob/main/examples/03_structured_output.py).
|
|
164
|
+
|
|
165
|
+
## Models and discovery
|
|
166
|
+
|
|
167
|
+
The short names below are convenience aliases. You can also pass a raw model ID from GMI Cloud's model catalog; other strings pass through unchanged.
|
|
168
|
+
|
|
169
|
+
| `ChatGMI` model | GMI model ID | Upstream context reference |
|
|
170
|
+
| --- | --- | --- |
|
|
171
|
+
| `deepseek-v3.2` | `gmi/deepseek-ai/DeepSeek-V3.2` | [163,840 configured positions](https://huggingface.co/deepseek-ai/DeepSeek-V3.2/blob/main/config.json) |
|
|
172
|
+
| `claude-sonnet-4.5` | `gmi/anthropic/claude-sonnet-4.5` | [200K tokens](https://platform.claude.com/docs/en/models/overview) |
|
|
173
|
+
| `claude-opus-4.5` | `gmi/anthropic/claude-opus-4.5` | [200K tokens](https://platform.claude.com/docs/en/models/overview) |
|
|
174
|
+
| `qwen3-vl` | `gmi/Qwen/Qwen3-VL-235B-A22B-Instruct-FP8` | [256K tokens, native](https://huggingface.co/Qwen/Qwen3-VL-235B-A22B-Instruct) |
|
|
175
|
+
| `gpt-5` | `gmi/openai/gpt-5` | [400,000 tokens](https://developers.openai.com/api/docs/models/gpt-5) |
|
|
176
|
+
| `gemini-3-flash` | `gmi/google/gemini-3-flash-preview` | [1,048,576 input tokens](https://ai.google.dev/gemini-api/docs/models/gemini-3-flash-preview) |
|
|
177
|
+
|
|
178
|
+
These are upstream references, not verified limits for GMI deployments. The DeepSeek value is its model configuration's position limit. Check the GMI catalog for deployment limits and current availability. The aliases above are fixed convenience mappings; use a raw ID from discovery if your account's catalog uses a different ID.
|
|
179
|
+
|
|
180
|
+
`list_gmi_models()` returns each API model record with a normalized `context_length` integer or `None` when the API does not report a value. It recognizes positive integer `context_length`, `max_model_len`, `max_context_length`, and `context_window` fields in that order. It preserves other API metadata and does not infer missing context lengths from this table.
|
|
181
|
+
|
|
182
|
+
```python
|
|
183
|
+
from langchain_gmi import list_gmi_models
|
|
184
|
+
|
|
185
|
+
for model in list_gmi_models():
|
|
186
|
+
print(model["id"], model["context_length"])
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
You can also call `list_gmi_models(api_key, base_url=..., timeout=30.0, client=httpx_client)`. A supplied HTTPX client stays open; internally created clients close after the request. HTTP errors raise `httpx.HTTPStatusError`, timeouts propagate, and malformed model-list responses raise `ValueError`. Discovery makes one request without automatic retries.
|
|
190
|
+
|
|
191
|
+
See [`examples/01_basic_chat.py`](https://github.com/dhruvil-codes/langchain-gmi/blob/main/examples/01_basic_chat.py) for chat, streaming, and discovery. GMI's [API reference](https://docs.gmicloud.ai/inference-engine/api-reference/llm-api-reference) documents `GET /v1/models` and `POST /v1/chat/completions`.
|
|
192
|
+
|
|
193
|
+
## Live validation
|
|
194
|
+
|
|
195
|
+
The integration was tested against GMI Cloud on November 14, 2026 with the catalog model `deepseek-ai/deepseek-v4.1-flash-1017`:
|
|
196
|
+
|
|
197
|
+
```python
|
|
198
|
+
llm = ChatGMI(model="deepseek-ai/deepseek-v4.1-flash-1017")
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Model discovery, sync/async chat, sync/async streaming, tool calling, and Pydantic structured output passed. See the [validation record](https://github.com/dhruvil-codes/langchain-gmi/blob/main/docs/live-validation.md) for scope and dependency versions. These are functional checks, not performance benchmarks.
|
|
202
|
+
|
|
203
|
+
## How it fits together
|
|
204
|
+
|
|
205
|
+
```mermaid
|
|
206
|
+
flowchart LR
|
|
207
|
+
A[Your application] --> B[LangChain ChatGMI]
|
|
208
|
+
B -->|OpenAI-compatible chat request| C[GMI Cloud API]
|
|
209
|
+
C --> D[Selected model]
|
|
210
|
+
D -->|chat response or streamed chunks| C
|
|
211
|
+
C --> B
|
|
212
|
+
B --> A
|
|
213
|
+
E[list_gmi_models] -->|GET /v1/models| C
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## Development
|
|
217
|
+
|
|
218
|
+
From a checkout of this repository:
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
pip install -e ".[dev]"
|
|
222
|
+
pytest
|
|
223
|
+
ruff check .
|
|
224
|
+
ruff format --check .
|
|
225
|
+
python -m build
|
|
226
|
+
twine check dist/*
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
Tests use mocked HTTP transports, with live HTTP blocked. CI checks Python 3.10 through 3.13 and a minimum LangChain dependency configuration. The MIT license is in [LICENSE](https://github.com/dhruvil-codes/langchain-gmi/blob/main/LICENSE).
|
|
230
|
+
|
|
231
|
+
## Links
|
|
232
|
+
|
|
233
|
+
- [GMI Cloud developers](https://www.gmicloud.ai/en/developers)
|
|
234
|
+
- [GMI Cloud inference API reference](https://docs.gmicloud.ai/inference-engine/api-reference/llm-api-reference)
|
|
235
|
+
- [LangChain chat models](https://docs.langchain.com/oss/python/langchain/models)
|
|
236
|
+
- [GMI Cloud console](https://console.gmicloud.ai/)
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# langchain-gmi
|
|
2
|
+
|
|
3
|
+
[](https://www.gmicloud.ai/en/developers) [](https://www.python.org/)
|
|
4
|
+
|
|
5
|
+
LangChain integration for GMI Cloud's OpenAI-compatible Inference Engine. Access DeepSeek V3.2, Claude Sonnet 4.5, and open models through one endpoint, alongside GMI Cloud's NVIDIA H100 GPU inference infrastructure. This is a community integration.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install langchain-gmi
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Set an API key in your environment:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
export GMI_API_KEY="your-gmi-api-key"
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
PowerShell:
|
|
20
|
+
|
|
21
|
+
```powershell
|
|
22
|
+
$env:GMI_API_KEY = "your-gmi-api-key"
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Requires Python 3.10 or newer. The default endpoint is `https://api.gmi-serving.com/v1`. The integration accepts `gmi_api_key`, `api_key`, or `openai_api_key`; `GMI_API_KEY` is the environment variable fallback. Explicit credentials take precedence. Missing or empty credentials raise `ValueError` during construction. `OPENAI_API_KEY` and OpenAI endpoint environment variables are not used to configure this provider.
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
llm = ChatGMI(
|
|
29
|
+
model="deepseek-v3.2",
|
|
30
|
+
# gmi_api_key=secret_from_your_secret_manager,
|
|
31
|
+
base_url="https://api.gmi-serving.com/v1",
|
|
32
|
+
timeout=60,
|
|
33
|
+
max_retries=2,
|
|
34
|
+
metadata={"application": "support"},
|
|
35
|
+
)
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Runs include `provider="gmi-cloud"` metadata and `ls_provider="gmi-cloud"` for tracing. API keys use Pydantic secret fields and are excluded from provider-specific exports.
|
|
39
|
+
|
|
40
|
+
## Quickstart
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
from langchain_gmi import ChatGMI
|
|
44
|
+
|
|
45
|
+
llm = ChatGMI(model="deepseek-v3.2")
|
|
46
|
+
response = llm.invoke("What makes GMI Cloud H100 clusters fast?")
|
|
47
|
+
print(response.content)
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
`ChatGMI` inherits LangChain's chat model methods, including `invoke`/`ainvoke`, `stream`/`astream`, `bind_tools`, and `with_structured_output`. Availability and behavior of model capabilities depend on the selected model and the API's current support.
|
|
51
|
+
|
|
52
|
+
## Async and streaming
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
import asyncio
|
|
56
|
+
|
|
57
|
+
from langchain_gmi import ChatGMI
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
async def main() -> None:
|
|
61
|
+
llm = ChatGMI(model="deepseek-v3.2")
|
|
62
|
+
|
|
63
|
+
response = await llm.ainvoke("Give me a one-sentence summary of inference APIs.")
|
|
64
|
+
print(response.content)
|
|
65
|
+
|
|
66
|
+
async for chunk in llm.astream("Count from one to three."):
|
|
67
|
+
print(chunk.content, end="", flush=True)
|
|
68
|
+
print()
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
if __name__ == "__main__":
|
|
72
|
+
asyncio.run(main())
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
For synchronous streaming:
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
for chunk in llm.stream("Count from one to three."):
|
|
79
|
+
print(chunk.content, end="", flush=True)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
If your selected model supports usage reporting, pass `stream_options={"include_usage": True}` to `stream` or `astream` and inspect the final chunk's `usage_metadata`. Streaming usage requests are opt-in for this endpoint. Recent `langchain-openai` versions also accept `stream_usage=True`.
|
|
83
|
+
|
|
84
|
+
## Tool calling
|
|
85
|
+
|
|
86
|
+
Bind LangChain tools to the model, then invoke it with a message. The model may return tool calls in `AIMessage.tool_calls`; your application is responsible for executing them and returning the results.
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
from langchain_core.tools import tool
|
|
90
|
+
|
|
91
|
+
from langchain_gmi import ChatGMI
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
@tool
|
|
95
|
+
def multiply(a: int, b: int) -> int:
|
|
96
|
+
"""Multiply two integers."""
|
|
97
|
+
return a * b
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
llm = ChatGMI(model="deepseek-v3.2").bind_tools([multiply])
|
|
101
|
+
message = llm.invoke("What is 6 times 7?")
|
|
102
|
+
print(message.tool_calls)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
See [`examples/02_agent_with_tools.py`](https://github.com/dhruvil-codes/langchain-gmi/blob/main/examples/02_agent_with_tools.py) for a bounded tool loop with calculator and web search tools.
|
|
106
|
+
|
|
107
|
+
## Structured output
|
|
108
|
+
|
|
109
|
+
Use a Pydantic model to validate extracted fields:
|
|
110
|
+
|
|
111
|
+
```python
|
|
112
|
+
from pydantic import BaseModel, Field
|
|
113
|
+
|
|
114
|
+
from langchain_gmi import ChatGMI
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
class SupportTicket(BaseModel):
|
|
118
|
+
"""Fields extracted from a short support request."""
|
|
119
|
+
|
|
120
|
+
category: str = Field(description="Short issue category")
|
|
121
|
+
urgency: int = Field(ge=1, le=5, description="Urgency from 1 (low) to 5 (high)")
|
|
122
|
+
summary: str
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
extract = ChatGMI(model="deepseek-v3.2").with_structured_output(SupportTicket)
|
|
126
|
+
ticket = extract.invoke("My account is locked and our team is blocked from a deadline.")
|
|
127
|
+
print(ticket)
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
The integration's default structured-output strategy is `function_calling`. See [`examples/03_structured_output.py`](https://github.com/dhruvil-codes/langchain-gmi/blob/main/examples/03_structured_output.py).
|
|
131
|
+
|
|
132
|
+
## Models and discovery
|
|
133
|
+
|
|
134
|
+
The short names below are convenience aliases. You can also pass a raw model ID from GMI Cloud's model catalog; other strings pass through unchanged.
|
|
135
|
+
|
|
136
|
+
| `ChatGMI` model | GMI model ID | Upstream context reference |
|
|
137
|
+
| --- | --- | --- |
|
|
138
|
+
| `deepseek-v3.2` | `gmi/deepseek-ai/DeepSeek-V3.2` | [163,840 configured positions](https://huggingface.co/deepseek-ai/DeepSeek-V3.2/blob/main/config.json) |
|
|
139
|
+
| `claude-sonnet-4.5` | `gmi/anthropic/claude-sonnet-4.5` | [200K tokens](https://platform.claude.com/docs/en/models/overview) |
|
|
140
|
+
| `claude-opus-4.5` | `gmi/anthropic/claude-opus-4.5` | [200K tokens](https://platform.claude.com/docs/en/models/overview) |
|
|
141
|
+
| `qwen3-vl` | `gmi/Qwen/Qwen3-VL-235B-A22B-Instruct-FP8` | [256K tokens, native](https://huggingface.co/Qwen/Qwen3-VL-235B-A22B-Instruct) |
|
|
142
|
+
| `gpt-5` | `gmi/openai/gpt-5` | [400,000 tokens](https://developers.openai.com/api/docs/models/gpt-5) |
|
|
143
|
+
| `gemini-3-flash` | `gmi/google/gemini-3-flash-preview` | [1,048,576 input tokens](https://ai.google.dev/gemini-api/docs/models/gemini-3-flash-preview) |
|
|
144
|
+
|
|
145
|
+
These are upstream references, not verified limits for GMI deployments. The DeepSeek value is its model configuration's position limit. Check the GMI catalog for deployment limits and current availability. The aliases above are fixed convenience mappings; use a raw ID from discovery if your account's catalog uses a different ID.
|
|
146
|
+
|
|
147
|
+
`list_gmi_models()` returns each API model record with a normalized `context_length` integer or `None` when the API does not report a value. It recognizes positive integer `context_length`, `max_model_len`, `max_context_length`, and `context_window` fields in that order. It preserves other API metadata and does not infer missing context lengths from this table.
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
from langchain_gmi import list_gmi_models
|
|
151
|
+
|
|
152
|
+
for model in list_gmi_models():
|
|
153
|
+
print(model["id"], model["context_length"])
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
You can also call `list_gmi_models(api_key, base_url=..., timeout=30.0, client=httpx_client)`. A supplied HTTPX client stays open; internally created clients close after the request. HTTP errors raise `httpx.HTTPStatusError`, timeouts propagate, and malformed model-list responses raise `ValueError`. Discovery makes one request without automatic retries.
|
|
157
|
+
|
|
158
|
+
See [`examples/01_basic_chat.py`](https://github.com/dhruvil-codes/langchain-gmi/blob/main/examples/01_basic_chat.py) for chat, streaming, and discovery. GMI's [API reference](https://docs.gmicloud.ai/inference-engine/api-reference/llm-api-reference) documents `GET /v1/models` and `POST /v1/chat/completions`.
|
|
159
|
+
|
|
160
|
+
## Live validation
|
|
161
|
+
|
|
162
|
+
The integration was tested against GMI Cloud on November 14, 2026 with the catalog model `deepseek-ai/deepseek-v4.1-flash-1017`:
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
llm = ChatGMI(model="deepseek-ai/deepseek-v4.1-flash-1017")
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Model discovery, sync/async chat, sync/async streaming, tool calling, and Pydantic structured output passed. See the [validation record](https://github.com/dhruvil-codes/langchain-gmi/blob/main/docs/live-validation.md) for scope and dependency versions. These are functional checks, not performance benchmarks.
|
|
169
|
+
|
|
170
|
+
## How it fits together
|
|
171
|
+
|
|
172
|
+
```mermaid
|
|
173
|
+
flowchart LR
|
|
174
|
+
A[Your application] --> B[LangChain ChatGMI]
|
|
175
|
+
B -->|OpenAI-compatible chat request| C[GMI Cloud API]
|
|
176
|
+
C --> D[Selected model]
|
|
177
|
+
D -->|chat response or streamed chunks| C
|
|
178
|
+
C --> B
|
|
179
|
+
B --> A
|
|
180
|
+
E[list_gmi_models] -->|GET /v1/models| C
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Development
|
|
184
|
+
|
|
185
|
+
From a checkout of this repository:
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
pip install -e ".[dev]"
|
|
189
|
+
pytest
|
|
190
|
+
ruff check .
|
|
191
|
+
ruff format --check .
|
|
192
|
+
python -m build
|
|
193
|
+
twine check dist/*
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Tests use mocked HTTP transports, with live HTTP blocked. CI checks Python 3.10 through 3.13 and a minimum LangChain dependency configuration. The MIT license is in [LICENSE](https://github.com/dhruvil-codes/langchain-gmi/blob/main/LICENSE).
|
|
197
|
+
|
|
198
|
+
## Links
|
|
199
|
+
|
|
200
|
+
- [GMI Cloud developers](https://www.gmicloud.ai/en/developers)
|
|
201
|
+
- [GMI Cloud inference API reference](https://docs.gmicloud.ai/inference-engine/api-reference/llm-api-reference)
|
|
202
|
+
- [LangChain chat models](https://docs.langchain.com/oss/python/langchain/models)
|
|
203
|
+
- [GMI Cloud console](https://console.gmicloud.ai/)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Live validation
|
|
2
|
+
|
|
3
|
+
On November 14, 2026, the package was tested against `https://api.gmi-serving.com/v1` using a private API key supplied by the maintainer. The key is not part of the source, release artifacts, or this record.
|
|
4
|
+
|
|
5
|
+
The selected catalog model was `deepseek-ai/deepseek-v4.1-flash-1017`. Discovery returned 75 models and reported `context_length=1048575` for the selected model. These values are a snapshot of that account's response.
|
|
6
|
+
|
|
7
|
+
| Check | Result | Observed behavior |
|
|
8
|
+
| --- | --- | --- |
|
|
9
|
+
| Model discovery | Passed | Authenticated `GET /v1/models` returned the catalog |
|
|
10
|
+
| Sync chat | Passed | `invoke` returned `OK` with finish reason `stop` |
|
|
11
|
+
| Async chat | Passed | `ainvoke` returned `OK` |
|
|
12
|
+
| Sync streaming | Passed | Streamed content assembled to `OK` |
|
|
13
|
+
| Async streaming | Passed | Async streamed content assembled to `OK` |
|
|
14
|
+
| Tool calling | Passed | Forced `Add` tool call returned arguments `a=2, b=3` |
|
|
15
|
+
| Structured output | Passed | Default function-calling strategy parsed `Answer(answer=5)` with no parsing error |
|
|
16
|
+
|
|
17
|
+
Live requests used `max_tokens=1024`, a 60-second timeout, and no automatic retries. The environment used Python 3.13.11, `langchain-openai==1.8.0`, `langchain-core==1.8.0`, `pydantic==2.14.3`, `httpx==0.28.1`, and `openai==3.51.0`.
|
|
18
|
+
|
|
19
|
+
Separately, all 73 offline tests passed under the current dependency configuration and under Python 3.11.11 with `langchain-openai==0.2.0`, `langchain-core==0.3.0`, `pydantic==2.5.2`, `httpx==0.27.0`, and `openai==1.40.0`. Ruff lint and format checks passed, and wheel and source distributions built successfully.
|
|
20
|
+
|
|
21
|
+
These checks establish basic functional compatibility for this model and account at the time of testing. They do not measure latency, throughput, GPU hardware, reliability under load, or feature support across every model.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""Basic ChatGMI usage and model discovery.
|
|
2
|
+
|
|
3
|
+
Set ``GMI_API_KEY`` before running. Calls are made only from ``main`` so this
|
|
4
|
+
file can be imported without contacting the API.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from langchain_gmi import ChatGMI, list_gmi_models
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def main() -> None:
|
|
11
|
+
llm = ChatGMI(model="deepseek-v3.2")
|
|
12
|
+
response = llm.invoke("What makes GMI Cloud H100 clusters fast?")
|
|
13
|
+
print(response.content)
|
|
14
|
+
|
|
15
|
+
print("\nStreaming:")
|
|
16
|
+
for chunk in llm.stream("Explain GPU inference in one sentence."):
|
|
17
|
+
print(chunk.content, end="", flush=True)
|
|
18
|
+
print()
|
|
19
|
+
|
|
20
|
+
print("\nModels available to this API key:")
|
|
21
|
+
for model in list_gmi_models():
|
|
22
|
+
print(f"- {model['id']}: context_length={model['context_length']}")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
if __name__ == "__main__":
|
|
26
|
+
main()
|