Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions docs/guides/embeddings.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@
The embedding interface shares the same `LLM` facade as chat.

```python
from republic import LLM
from republic import LLM, RepublicError

llm = LLM(model="openrouter:openai/text-embedding-3-small", api_key="<API_KEY>")
out = llm.embed(["republic", "tape-first"])

if out.error:
print(out.error.kind, out.error.message)
else:
print(out.value)
try:
out = llm.embed(["republic", "tape-first"])
print(out)
except RepublicError as error:
print(error.kind, error.message)
```

You can also override the model per call:
Expand Down
26 changes: 14 additions & 12 deletions docs/guides/text.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,27 @@
## if_

```python
from republic import LLM
from republic import LLM, RepublicError

llm = LLM(model="openrouter:openai/gpt-4o-mini", api_key="<API_KEY>")
decision = llm.if_("The release is blocked by a migration failure.", "Should we page on-call now?")

print(decision.value) # bool | None
print(decision.error)
try:
decision = llm.if_("The release is blocked by a migration failure.", "Should we page on-call now?")
print(decision) # bool
except RepublicError as error:
print(error.kind, error.message)
```

## classify

```python
label = llm.classify(
"User asks for invoice and tax receipt.",
["sales", "support", "finance"],
)

print(label.value) # one of choices | None
print(label.error)
try:
label = llm.classify(
"User asks for invoice and tax receipt.",
["sales", "support", "finance"],
)
print(label) # one of choices
except RepublicError as error:
print(error.kind, error.message)
```

## Usage Tips
Expand Down
14 changes: 10 additions & 4 deletions docs/guides/tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,16 @@ print(out.error)
## Manual Execution (More Control)

```python
calls = llm.tool_calls("Use get_weather for Berlin.", tools=[get_weather])
execution = llm.tools.execute(calls, tools=[get_weather])
print(execution.tool_results)
print(execution.error)
from republic import RepublicError

try:
calls = llm.tool_calls("Use get_weather for Berlin.", tools=[get_weather])
execution = llm.tools.execute(calls, tools=[get_weather])
except RepublicError as error:
print(error.kind, error.message)
else:
print(execution.tool_results)
print(execution.error)
```

## Tools with Context
Expand Down
14 changes: 6 additions & 8 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,20 @@ Use LLM capabilities like regular Python components, with auditable execution tr
Republic is not a bigger framework. It is a small set of composable primitives:

- `LLM`: One entry point for chat, tools, stream, and embeddings.
- `StructuredOutput`: Key interfaces return `value + error`.
- `Tape`: Append-only records with anchor/handoff/context/query.
- `ToolExecutor`: Tool calls can be automatic or manual.

## 30-Second Preview

```python
from republic import LLM
from republic import LLM, RepublicError

llm = LLM(model="openrouter:openrouter/free", api_key="<API_KEY>")
out = llm.chat("Explain tape-first in one sentence.", max_tokens=48)

if out.error:
print(out.error.kind, out.error.message)
else:
print(out.value)
try:
out = llm.chat("Explain tape-first in one sentence.", max_tokens=48)
print(out)
except RepublicError as error:
print(error.kind, error.message)
```

## What You Get
Expand Down
12 changes: 6 additions & 6 deletions examples/01_quickstart_chat.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import os

from republic import LLM
from republic import LLM, RepublicError


class MissingEnvVarError(RuntimeError):
Expand All @@ -22,12 +22,12 @@ def main() -> None:
model = os.getenv("REPUBLIC_CHAT_MODEL", "openrouter:openrouter/free")

llm = LLM(model=model, api_key=api_key)
out = llm.chat("Explain tape-first in one sentence.", max_tokens=48)

if out.error:
print("error:", out.error.kind, out.error.message)
try:
out = llm.chat("Explain tape-first in one sentence.", max_tokens=48)
except RepublicError as error:
print("error:", error.kind, error.message)
return
print("text:", out.value)
print("text:", out)


if __name__ == "__main__":
Expand Down
26 changes: 14 additions & 12 deletions examples/02_tools_auto_and_manual.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from pydantic import BaseModel

from republic import LLM, ToolContext, tool, tool_from_model
from republic import LLM, RepublicError, ToolContext, tool, tool_from_model


class MissingEnvVarError(RuntimeError):
Expand Down Expand Up @@ -52,23 +52,25 @@ def main() -> None:
print(auto.kind, auto.tool_results, auto.error)

print("== manual tools ==")
calls = llm.tool_calls("Use get_weather for Berlin.", tools=[get_weather])
if calls.error:
print("tool call error:", calls.error)
try:
calls = llm.tool_calls("Use get_weather for Berlin.", tools=[get_weather])
manual = llm.tools.execute(calls, tools=[get_weather])
except RepublicError as error:
print("tool call error:", error.kind, error.message)
return
manual = llm.tools.execute(calls.value, tools=[get_weather])
print(manual.tool_results, manual.error)

print("== pydantic tool ==")
ticket_tool = tool_from_model(Ticket, create_ticket)
ticket_calls = llm.tool_calls(
"Create a ticket with title 'db timeout' and severity 'high'.",
tools=[ticket_tool],
)
if ticket_calls.error:
print("ticket error:", ticket_calls.error)
try:
ticket_calls = llm.tool_calls(
"Create a ticket with title 'db timeout' and severity 'high'.",
tools=[ticket_tool],
)
ticket_exec = llm.tools.execute(ticket_calls, tools=[ticket_tool])
except RepublicError as error:
print("ticket error:", error.kind, error.message)
return
ticket_exec = llm.tools.execute(ticket_calls.value, tools=[ticket_tool])
print(ticket_exec.tool_results, ticket_exec.error)

print("== context tool with tape ==")
Expand Down
11 changes: 6 additions & 5 deletions examples/05_text_and_embeddings.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,22 @@ def main() -> None:
"The checkout API has 30% errors after deployment.",
"Should we trigger rollback now?",
)
print("if:", decision.value, decision.error)
print("if:", decision)

label = llm.classify(
"Need VAT invoice and payment receipt.",
["sales", "support", "finance"],
)
print("classify:", label.value, label.error)
print("classify:", label)

emb_out = llm.embed(
["checkout incident", "rollback decision"],
model=embedding_model,
)
print("embeddings error:", emb_out.error)
if emb_out.error is None:
print("embeddings value type:", type(emb_out.value).__name__)

print("embeddings type:", type(emb_out).__name__)
emb_data = emb_out.data if hasattr(emb_out, "data") else emb_out.get("data", [])
print("embedding count:", len(emb_data))


if __name__ == "__main__":
Expand Down
Loading