mirror of
https://github.com/langchain-ai/langchain.git
synced 2026-10-05 09:25:14 +03:00
Adds a first-party `langchain-typesafe` partner package for making
structured decisions using the new and shiny `jev` model. It introduces
a new `TypeSafeClassifier` runnable while using the typesafe wire
protocol, message normalization, response parsing, and provider failures
behind a standard LangChain interface.
- Supports TypeSafe's `Choice`, `Noul`, and `Score` primitives with
typed answers, probabilities, confidence, usage metadata, and request
IDs.
- Resolves credentials and API configuration from explicit arguments or
`TYPESAFE_API_KEY` and `TYPESAFE_BASE_URL`.
- Supports injected `httpx2.Client` and `httpx2.AsyncClient` instances
for custom transports, proxies, test fixtures, and shared connection
pools (matching patterns of other provider packages in this repo)
---
There were a couple of rapid fire design decisions that I'll document
here to aid in review:
### Extending base `Runnable`
This is largely the impetus for this PR; we can use typesafe's native
python client, but we lose tracing if it isn't captured through the
runnable interface. I imagine because this is a different model we want
to attribute its costs and things in tracing (at a later point in time)
### Direct `httpx2` integration
This package implements the System One `POST /v1/systemone` contract
directly rather than wrapping `typesafe-sdk` (the status quo of other
integrations in langchain). This keeps the integration's public types
and behavior native, avoids adding a transitive dependency, and gives us
lower level controls which is harder to do when indirecting through
someone elses client.
Aspirationally this is a direction we've wanted to work towards for
integrations generally:
* The benefit of wrapping an external sdk is that we can stay tied to
the supply-chain of a package thats maintained first party (we don't
need to maintain types, the transitive dependency keeps capabilities up
to date, etc.)
* This was in a time when maintainer attention was limited, and the
focus wasn't on nitty gritty implementation details with a provider
* ^Agents are probably good enough to start shouldering most of the
burden we've encountered in the past
* There's an indirection tax we have to pay when we shove the
responsibility onto a separate package- it makes us harder to design
single abstractions around
Because this is a 0-1 integration, my intention is to trial typesafes'
implementation under a "langchain maintained client" paradigm to see if
this is something that could work more generally
### State typing and message normalization
I had to bifurcate the input state types into `State` and `_StateValue`
representations mostly to respect TypeSafe API invariants: input must be
a string, object, or array. Its private recursive `_StateValue`
representation permits ordinary scalars by itself and through
dicts/sequences.
I'm also adding langchain `BaseMessage` objects and `BaseMessage`
sequences at any nesting level. This is because messages are the most
common unit of context within langchain, and translating between agent
context and classifier context is a very important part of us plugging
jev into the ecosystem. I'm imagining something like this:
```python
class ClassifierMiddleware(AgentMiddleware[AgentState, ContextT, ResponseT]):
def after_model(self, state):
result = TypeSafeClassifier(...).invoke(state.messages)
# do something with results
```
This uses the `convert_to_openai_messages` utility exposed in core since
that is the most context friendly representation we have to pass
messages through to typesafe (which doesn't have any concept of an LLM
message)
### Typed request and response models
Question and answer models use Pydantic because they sit directly on
serialization and validation layers, and I was hoping to meet some of
the invariant criteria that the typesafe API has. Things like:
* request models requiring instructions for every question
* `Score` requiring at least two ordered levels
* rejecting empty model identifiers
Criteria remain JSON-capable rather than being narrowed to strings
because TypeSafe's advanced documentation supports structured
instructions and criteria, even though the compact HTTP reference
presents narrower examples.
(lmk if pydantic is defunct and we should pivot)
### Error handling infrastructure
I wanted to meet the same level of specification that the TypeSafe
Python SDK has with regards to how it represents errors. This package
exports a standard error reference (in `_client_utils.py`) that does
this while also inheriting from alngchains standard `Model*Error`
classes which we recently added. Callers can handle either
TypeSafe-specific metadata or provider-independent model failures.
The package mirrors the TypeSafe Python SDK's status, connection,
timeout, rate-limit, and response-validation exception names.
Status-specific provider errors also inherit from LangChain's standard
`Model*Error` classes, following the OpenAI integration pattern, so
callers can handle either TypeSafe-specific metadata or
provider-independent model failures.
API errors retain structured status, body, headers, request ID,
sanitized endpoint, response-validation field path, and rate-limit delay
metadata where applicable. TypeSafe's `529 Overloaded` response maps to
a retryable `ModelAPIError`, while `429` maps to `ModelRateLimitError`
and preserves `retry_after_ms`.
Automatic retry policy is intentionally outside the initial package
scope. The classified retryable errors and retry metadata provide the
foundation for a focused follow-up without coupling this integration to
a retry policy in its first release.
## Package infrastructure
- Introduces `langchain-typesafe` at version `0.0.1` with typed-package
markers, documentation, unit and integration-compilation coverage, and a
reproducible `uv` lockfile.
- Adds bounded `httpx2>=2.0.0,<3.0.0` and `langchain-core>=1.6.2,<2.0.0`
dependencies. The core minimum provides the standard `Model*Error`
hierarchy used by the provider exceptions.
- Registers the package with repository CI, release automation,
dependency updates, issue routing, and package labeling.
## Release note
Added the new `langchain-typesafe` integration package, including a
composable `TypeSafeClassifier` for typed classification, scoring, and
confidence-aware decisions with TypeSafe's Jev model.
---
This was developed with heavy assistance from Sol, earnestly reviewed by
me, and validated through similar CI patterns established in other
packages
122 lines
3.8 KiB
YAML
122 lines
3.8 KiB
YAML
name: "📋 Task"
|
|
description: Create a task for project management and tracking by LangChain maintainers. If you are not a maintainer, please use other templates or the forum.
|
|
labels: ["task"]
|
|
type: task
|
|
body:
|
|
- type: markdown
|
|
attributes:
|
|
value: |
|
|
Thanks for creating a task to help organize LangChain development.
|
|
|
|
This template is for **maintainer tasks** such as project management, development planning, refactoring, documentation updates, and other organizational work.
|
|
|
|
If you are not a LangChain maintainer or were not asked directly by a maintainer to create a task, then please start the conversation on the [LangChain Forum](https://forum.langchain.com/) instead or use the appropriate bug report or feature request templates on the previous page.
|
|
- type: checkboxes
|
|
id: maintainer
|
|
attributes:
|
|
label: Maintainer task
|
|
description: Confirm that you are allowed to create a task here.
|
|
options:
|
|
- label: I am a LangChain maintainer, or was asked directly by a LangChain maintainer to create a task here.
|
|
required: true
|
|
- type: textarea
|
|
id: task-description
|
|
attributes:
|
|
label: Task Description
|
|
description: |
|
|
Provide a clear and detailed description of the task.
|
|
|
|
What needs to be done? Be specific about the scope and requirements.
|
|
placeholder: |
|
|
This task involves...
|
|
|
|
The goal is to...
|
|
|
|
Specific requirements:
|
|
- ...
|
|
- ...
|
|
validations:
|
|
required: true
|
|
- type: textarea
|
|
id: acceptance-criteria
|
|
attributes:
|
|
label: Acceptance Criteria
|
|
description: |
|
|
Define the criteria that must be met for this task to be considered complete.
|
|
|
|
What are the specific deliverables or outcomes expected?
|
|
placeholder: |
|
|
This task will be complete when:
|
|
- [ ] ...
|
|
- [ ] ...
|
|
- [ ] ...
|
|
validations:
|
|
required: true
|
|
- type: textarea
|
|
id: context
|
|
attributes:
|
|
label: Context and Background
|
|
description: |
|
|
Provide any relevant context, background information, or links to related issues/PRs.
|
|
|
|
Why is this task needed? What problem does it solve?
|
|
placeholder: |
|
|
Background:
|
|
- ...
|
|
|
|
Related issues/PRs:
|
|
- #...
|
|
|
|
Additional context:
|
|
- ...
|
|
validations:
|
|
required: false
|
|
- type: textarea
|
|
id: dependencies
|
|
attributes:
|
|
label: Dependencies
|
|
description: |
|
|
List any dependencies or blockers for this task.
|
|
|
|
Are there other tasks, issues, or external factors that need to be completed first?
|
|
placeholder: |
|
|
This task depends on:
|
|
- [ ] Issue #...
|
|
- [ ] PR #...
|
|
- [ ] External dependency: ...
|
|
|
|
Blocked by:
|
|
- ...
|
|
validations:
|
|
required: false
|
|
- type: checkboxes
|
|
id: package
|
|
attributes:
|
|
label: Package (Required)
|
|
description: |
|
|
Please select package(s) that this task is related to.
|
|
options:
|
|
- label: langchain
|
|
- label: langchain-openai
|
|
- label: langchain-anthropic
|
|
- label: langchain-classic
|
|
- label: langchain-core
|
|
- label: langchain-model-profiles
|
|
- label: langchain-tests
|
|
- label: langchain-text-splitters
|
|
- label: langchain-chroma
|
|
- label: langchain-deepseek
|
|
- label: langchain-exa
|
|
- label: langchain-fireworks
|
|
- label: langchain-groq
|
|
- label: langchain-huggingface
|
|
- label: langchain-mistralai
|
|
- label: langchain-nomic
|
|
- label: langchain-ollama
|
|
- label: langchain-openrouter
|
|
- label: langchain-perplexity
|
|
- label: langchain-qdrant
|
|
- label: langchain-typesafe
|
|
- label: langchain-xai
|
|
- label: Other / not sure / general
|