# langinsight-langchain

LangInsight callback handler for LangChain. Sends input/output traces to LangInsight in parallel on each LLM end and supports feedback (thumbs up/down) via `score()`. TypeScript の `@langinsight/langchain` と同じ仕様です。

## Installation

```bash
pip install langinsight-langchain
```

Or with Poetry:

```bash
poetry add langinsight-langchain
```

## Usage

### Basic usage

```python
from langchain_anthropic import ChatAnthropic
from langinsight_langchain import CallbackHandler

import os

model = ChatAnthropic(model="claude-3-7-sonnet-20250219")

handler = CallbackHandler(
    api_key=os.environ["LANGINSIGHT_API_KEY"],
    endpoint=os.environ["LANGINSIGHT_ENDPOINT"],
    metadata={"userId": "admin", "sessionId": "admin"},
    on_success=lambda input_trace, output_trace: print("Trace sent:", output_trace.get("id")),
    on_failure=lambda err: print("Trace failed:", err),
)

response = model.invoke("hi!", config={"callbacks": [handler]})
```

### Feedback (score)

Trace ID は `handler.result.result()` で取得し、その `output_trace["id"]` を `score()` に渡してフィードバックを送信する。DB 永続化などは `on_success` コールバックでも行える。

```python
from langinsight_langchain import CallbackHandler

handler = CallbackHandler(
    api_key=os.environ["LANGINSIGHT_API_KEY"],
    endpoint=os.environ["LANGINSIGHT_ENDPOINT"],
    metadata={"userId": "admin", "sessionId": "admin"},
)

response = model.invoke("hi!", config={"callbacks": [handler]})

input_trace, output_trace = handler.result.result(timeout=10)
handler.score(trace_id=output_trace["id"], value=1)   # 👍
handler.score(trace_id=output_trace["id"], value=-1)  # 👎
```

## Options

| Option | Type | Required | Description |
|--------|------|----------|-------------|
| `api_key` | `str` | Yes | LangInsight API key |
| `endpoint` | `str` | Yes | LangInsight API endpoint (e.g. `https://api.langinsight.example.com`) |
| `metadata` | `dict` | Yes | Metadata attached to traces |
| `metadata.userId` | `str` | Yes | User ID |
| `metadata.sessionId` | `str` | Yes | Session ID (e.g. conversation id) |
| `metadata.modelName` | `str` | No | Model name (defaults to run metadata when not set) |
| `metadata.*` | `any` | No | Additional key-value pairs |
| `on_success` | `(input_trace, output_trace) -> None` | No | Callback when trace submission succeeds. Use `output_trace["id"]` as traceId. |
| `on_failure` | `(error: Exception) -> None` | No | Callback when trace submission fails |

## API

- **`score(trace_id, value)`** — Submits feedback (1 = thumbs up, -1 = thumbs down) for the given trace. Use `(handler.result.result())[1]["id"]` as `trace_id`.
- **`result`** — A `concurrent.futures.Future` that resolves to `(input_trace, output_trace)` when both traces are sent. Use `handler.result.result(timeout=10)` to block and get the traces.

## Development

```bash
poetry install
poetry run python examples/basic_usage.py
```

## License

MIT
