LLM Client Integration for LangChain with Chain-of-Thought Support
This package provides a seamless integration between custom LLM clients (e.g., DeepSeek, GLM, Qwen) and LangChain’s BaseChatModel, with built-in support for chain-of-thought (CoT) reasoning, structured output parsing, and both synchronous/asynchronous streaming.
Designed for developers who want fine-grained control over LLM interactions while leveraging LangChain’s ecosystem (e.g., callbacks, astream_events, tools, agents), this implementation wraps any OpenAI-compatible API into a fully compliant LangChain chat model.
📦 Features
- ✅ LangChain-Compatible Chat Model: Implements
BaseChatModelwith full support for sync/async, streaming/non-streaming. - 🔗 Chain-of-Thought (Thinking) Mode: Enable or disable CoT reasoning per model (GLM, Qwen, DeepSeek).
- 🧠 Custom Message Types:
ChatMessageandChatMessageChunkpreserve raw LLM responses (ChatCompletion/ChatCompletionChunk). - 📐 Structured Output Parsing:
SchemaParsergenerates schema-aware prompts and robustly parses LLM responses into Pydantic models. - ⚙️ Flexible LLM Client: Configurable base URL, API key fallbacks, and dynamic reconfiguration.
- 🌐 Streaming Support: Full compatibility with LangChain’s event streaming (
astream_events, callbacks).
🗂️ Project Structure
lingua-agent/
├── pyproject.toml # ← MUST contain project metadata & deps
├── README.md
├── LICENSE
└── src/
└── lingua_agent/ # ← top-level package name
├── __init__.py
├── llm_api/ # ← core LLM integration
│ ├── __init__.py
│ ├── llm_client.py
│ ├── llm_client_chat_model.py
│ ├── message_chunk.py
│ └── thinking_config.py
└── utils/ # ← helpers
├── __init__.py
└── schema_parse.py
🚀 Quick Start
1. Install Dependencies
pip install langchain-core openai pydantic
2. Initialize the LLM Client
from llm_client import LLMClient
llm_client = LLMClient(
model="deepseek-chat",
api_key="your-api-key",
enable_thinking=True # Enable chain-of-thought if supported
)
3. Wrap as LangChain Chat Model
from llm_client_chat_model import LLMClientChatModel
chat_model = LLMClientChatModel(llm_client=llm_client)
4. Use with LangChain
from langchain_core.messages import HumanMessage
# Non-streaming
response = chat_model.invoke([HumanMessage(content="Explain quantum computing.")])
print(response.content)
# Streaming
for chunk in chat_model.stream([HumanMessage(content="Write a haiku.")]):
print(chunk.content, end="", flush=True)
5. Parse Structured Output
from pydantic import BaseModel
from schema_parser import SchemaParser
class Answer(BaseModel):
summary: str
keywords: list[str]
parser = SchemaParser(Answer)
prompt = parser.schema_generation_prompt + "\n\nUser: Summarize climate change."
response = chat_model.invoke([HumanMessage(content=prompt)])
answer: Answer = parser.parse_response_to_base_model(response.content)
🔧 Configuration
Supported Models & CoT Parameters
| Model Prefix | Enable Thinking | Disable Thinking |
|---|---|---|
glm |
{"thinking": {"type": "enabled"}} |
{"thinking": {"type": "disabled"}} |
qwen |
{"enable_thinking": True} |
{"enable_thinking": False} |
deepseek |
{} (no extra params) |
{} |
The
LLMClientauto-detects model type and injects parameters viaextra_body.
API Key Resolution
The client checks environment variables in order:
DEEPSEEK_API_KEYOPENAI_API_KEYZHIPU_API_KEYAPI_KEY
📝 Notes
- Streaming Merge:
merge_chunks_to_completion()reconstructs fullChatCompletionfrom chunks, including usage stats and custom fields likereasoning_content. - Error Resilience:
SchemaParseruses fallback strategies to extract JSON from LLM responses (code blocks, raw JSON). - Callbacks: Fully supports LangChain’s callback system (
on_llm_new_token,astream_events, etc.).
📜 License
MIT License — feel free to use, modify, and distribute.
Built for researchers and developers who need reliable, structured, and introspectable LLM interactions within the LangChain framework.
Metadata
Release files for LangLLM 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| langllm-0.1.0.tar.gz | 10.6 kB | Without provenance | Details for langllm-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| langllm-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for langllm-0.1.0-py3-none-any.whl |
Total release size: 23.6 kB
Release files / langllm-0.1.0.tar.gz
| Download URL | langllm-0.1.0.tar.gz |
|---|---|
| Size | 10.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9222dc3a548f0c0f98503d55da7864038f58ed1222cf11290daacc6ef5f412fb
|
|
BLAKE2b-256 checksum How to use checksums |
84632f96a53b282316323a506171b999f25ac49a2a0fcee21e121313c1ac9220
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.3
|
Release files / langllm-0.1.0-py3-none-any.whl
| Download URL | langllm-0.1.0-py3-none-any.whl |
|---|---|
| Size | 13.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c1ca91a8d296dca67aebfcc1bfb3460a665e6c772f3633ac65120d59756a5d78
|
|
BLAKE2b-256 checksum How to use checksums |
d1e36e6819c6b057f5c2b7af6bca9635f3de794444a3dca8e96eb47b4d0fd4b3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.3
|
Security for LangLLM 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.