or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdembeddings.mdindex.mdmodels-and-conversations.mdplugins.mdtemplates.mdtools-and-toolboxes.md

models-and-conversations.mddocs/

0

# Models and Conversations

1

2

Core model management, conversation handling, prompt processing, and response streaming functionality. This module provides both synchronous and asynchronous APIs for interacting with Large Language Models from multiple providers.

3

4

## Capabilities

5

6

### Model Discovery and Management

7

8

The package provides functions to discover, retrieve, and manage models from various providers through a plugin-based registration system.

9

10

```python { .api }

11

def get_model(name: Optional[str] = None) -> Model:

12

"""

13

Get a model by name or alias. Returns the default model if name is None.

14

15

Args:

16

name: Model name or alias. Uses default if None.

17

18

Returns:

19

Model instance

20

21

Raises:

22

UnknownModelError: If model name/alias not found

23

"""

24

25

def get_async_model(name: Optional[str] = None) -> AsyncModel:

26

"""

27

Get an async model by name or alias. Returns default async model if name is None.

28

29

Args:

30

name: Model name or alias. Uses default if None.

31

32

Returns:

33

AsyncModel instance

34

35

Raises:

36

UnknownModelError: If async model name/alias not found

37

"""

38

39

def get_models() -> List[Model]:

40

"""Get all registered synchronous models."""

41

42

def get_async_models() -> List[AsyncModel]:

43

"""Get all registered asynchronous models."""

44

45

def get_models_with_aliases() -> List[ModelWithAliases]:

46

"""Get models with their configured aliases."""

47

48

def get_model_aliases() -> Dict[str, Model]:

49

"""Get mapping of all aliases to their corresponding models."""

50

51

def get_async_model_aliases() -> Dict[str, AsyncModel]:

52

"""Get mapping of all aliases to their corresponding async models."""

53

```

54

55

### Model Hierarchy

56

57

The package defines an abstract model hierarchy supporting both synchronous and asynchronous operations.

58

59

```python { .api }

60

class Model(ABC):

61

"""Abstract base class for synchronous LLM models."""

62

model_id: str

63

64

@abstractmethod

65

def prompt(self, prompt: Prompt, **kwargs) -> Response:

66

"""Execute a prompt and return response."""

67

68

def conversation(self, **kwargs) -> Conversation:

69

"""Create a new conversation with this model."""

70

71

class KeyModel(Model):

72

"""Abstract base for models requiring API keys."""

73

needs_key: str

74

key_env_var: Optional[str] = None

75

76

def __init__(self, key: Optional[str] = None):

77

"""Initialize with optional API key."""

78

79

class AsyncModel(ABC):

80

"""Abstract base class for asynchronous LLM models."""

81

model_id: str

82

83

@abstractmethod

84

async def prompt(self, prompt: Prompt, **kwargs) -> AsyncResponse:

85

"""Execute a prompt asynchronously and return response."""

86

87

def conversation(self, **kwargs) -> AsyncConversation:

88

"""Create a new async conversation with this model."""

89

90

class AsyncKeyModel(AsyncModel):

91

"""Abstract base for async models requiring API keys."""

92

needs_key: str

93

key_env_var: Optional[str] = None

94

95

def __init__(self, key: Optional[str] = None):

96

"""Initialize with optional API key."""

97

98

class ModelWithAliases:

99

"""Container for a model with its aliases."""

100

model: Model

101

async_model: Optional[AsyncModel]

102

aliases: List[str]

103

104

class Options(BaseModel):

105

"""Pydantic model for model configuration options."""

106

model_config = ConfigDict(extra="forbid")

107

```

108

109

### Conversation Management

110

111

Conversations maintain state and history across multiple prompt-response interactions.

112

113

```python { .api }

114

class Conversation:

115

"""Synchronous conversation management with tool chaining support."""

116

117

def __init__(self, model: Optional[Model] = None, conversation_id: Optional[str] = None):

118

"""

119

Initialize conversation.

120

121

Args:

122

model: Model to use for conversation

123

conversation_id: Optional conversation ID for persistence

124

"""

125

126

def prompt(

127

self,

128

prompt: Union[str, Prompt],

129

*,

130

attachments: Optional[List[Attachment]] = None,

131

tools: Optional[List[Tool]] = None,

132

stream: bool = False,

133

**kwargs

134

) -> Response:

135

"""

136

Send a prompt and get response.

137

138

Args:

139

prompt: Text prompt or Prompt object

140

attachments: Optional file/URL attachments

141

tools: Optional tools for function calling

142

stream: Whether to stream response

143

**kwargs: Additional model options

144

145

Returns:

146

Response object with text and metadata

147

"""

148

149

def responses(self) -> List[Response]:

150

"""Get all responses in conversation history."""

151

152

class AsyncConversation:

153

"""Asynchronous conversation management with tool chaining support."""

154

155

def __init__(self, model: Optional[AsyncModel] = None, conversation_id: Optional[str] = None):

156

"""Initialize async conversation."""

157

158

async def prompt(

159

self,

160

prompt: Union[str, Prompt],

161

*,

162

attachments: Optional[List[Attachment]] = None,

163

tools: Optional[List[Tool]] = None,

164

stream: bool = False,

165

**kwargs

166

) -> AsyncResponse:

167

"""Send a prompt asynchronously and get response."""

168

169

async def responses(self) -> List[AsyncResponse]:

170

"""Get all responses in conversation history."""

171

```

172

173

### Prompt System

174

175

The Prompt class provides a rich container for input data including text, attachments, tools, and structured schemas.

176

177

```python { .api }

178

class Prompt:

179

"""Container for prompts with tools, schema, and attachments."""

180

181

def __init__(

182

self,

183

prompt: Optional[str] = None,

184

*,

185

system: Optional[str] = None,

186

attachments: Optional[List[Attachment]] = None,

187

tools: Optional[List[Tool]] = None,

188

tool_choice: Optional[str] = None,

189

schema: Optional[dict] = None,

190

options: Optional[Options] = None

191

):

192

"""

193

Initialize prompt.

194

195

Args:

196

prompt: Main prompt text

197

system: System message

198

attachments: File/URL attachments

199

tools: Available tools for function calling

200

tool_choice: Tool selection strategy

201

schema: JSON schema for structured output

202

options: Model configuration options

203

"""

204

205

def __str__(self) -> str:

206

"""Return prompt text."""

207

208

class Attachment:

209

"""File/URL/binary content attachment to prompts."""

210

211

def __init__(

212

self,

213

type: Optional[str] = None,

214

path: Optional[str] = None,

215

url: Optional[str] = None,

216

content: Optional[bytes] = None

217

):

218

"""

219

Initialize attachment.

220

221

Args:

222

type: MIME type

223

path: File path

224

url: URL to content

225

content: Binary content

226

"""

227

228

def id(self) -> str:

229

"""Generate content hash ID."""

230

231

def resolve_type(self) -> str:

232

"""Determine MIME type from content/path/URL."""

233

234

def content_bytes(self) -> bytes:

235

"""Get content as bytes."""

236

237

def base64_content(self) -> str:

238

"""Get base64-encoded content."""

239

```

240

241

### Response Handling

242

243

Response objects provide access to model output with support for streaming, tool calls, and metadata.

244

245

```python { .api }

246

class Response:

247

"""Synchronous response object with streaming support."""

248

249

def text(self) -> str:

250

"""Get complete response text."""

251

252

def __iter__(self) -> Iterator[str]:

253

"""Stream response text chunks."""

254

255

def tool_calls(self) -> List[ToolCall]:

256

"""Get tool calls made during response."""

257

258

def usage(self) -> Usage:

259

"""Get token usage information."""

260

261

def response_json(self) -> Optional[dict]:

262

"""Get structured JSON response if schema was provided."""

263

264

class AsyncResponse:

265

"""Asynchronous response object for streaming/awaitable results."""

266

267

async def text(self) -> str:

268

"""Get complete response text asynchronously."""

269

270

def __aiter__(self) -> AsyncIterator[str]:

271

"""Stream response text chunks asynchronously."""

272

273

async def tool_calls(self) -> List[ToolCall]:

274

"""Get tool calls made during response."""

275

276

async def usage(self) -> Usage:

277

"""Get token usage information."""

278

279

async def response_json(self) -> Optional[dict]:

280

"""Get structured JSON response if schema was provided."""

281

282

class ChainResponse(Response):

283

"""Synchronous chained tool execution response."""

284

285

def responses(self) -> List[Response]:

286

"""Get all responses in the tool chain."""

287

288

class AsyncChainResponse(AsyncResponse):

289

"""Asynchronous chained tool execution response."""

290

291

async def responses(self) -> List[AsyncResponse]:

292

"""Get all responses in the tool chain."""

293

```

294

295

### Usage Tracking

296

297

The Usage class tracks token consumption and provides detailed usage statistics.

298

299

```python { .api }

300

class Usage:

301

"""Token usage tracking with detailed breakdown."""

302

303

def __init__(

304

self,

305

input: Optional[int] = None,

306

output: Optional[int] = None,

307

details: Optional[Dict[str, Any]] = None

308

):

309

"""

310

Initialize usage tracking.

311

312

Args:

313

input: Input token count

314

output: Output token count

315

details: Additional usage details

316

"""

317

318

input: Optional[int]

319

output: Optional[int]

320

details: Optional[Dict[str, Any]]

321

```

322

323

## Error Handling

324

325

The models module defines several exception classes for error handling:

326

327

```python { .api }

328

class ModelError(Exception):

329

"""Base exception for model-related errors."""

330

331

class NeedsKeyException(ModelError):

332

"""Raised when API key is required but missing."""

333

334

class UnknownModelError(KeyError):

335

"""Raised when model name or alias is not found."""

336

```

337

338

## Usage Examples

339

340

### Basic Model Usage

341

342

```python

343

import llm

344

345

# Get default model and send prompt

346

model = llm.get_model()

347

response = model.prompt("What is machine learning?")

348

print(response.text())

349

350

# Use specific model

351

model = llm.get_model("gpt-4")

352

response = model.prompt("Explain quantum computing in simple terms")

353

print(response.text())

354

```

355

356

### Streaming Responses

357

358

```python

359

import llm

360

361

model = llm.get_model()

362

response = model.prompt("Write a short story", stream=True)

363

364

# Stream response chunks

365

for chunk in response:

366

print(chunk, end="", flush=True)

367

print() # Final newline

368

```

369

370

### Conversation with History

371

372

```python

373

import llm

374

375

model = llm.get_model("claude-3-sonnet")

376

conversation = model.conversation()

377

378

# Multi-turn conversation

379

response1 = conversation.prompt("My name is Alice. What's a good hobby?")

380

print("Assistant:", response1.text())

381

382

response2 = conversation.prompt("Can you suggest books about that hobby?")

383

print("Assistant:", response2.text())

384

385

# Access conversation history

386

for response in conversation.responses():

387

print(f"Usage: {response.usage()}")

388

```

389

390

### Async Operations

391

392

```python

393

import asyncio

394

import llm

395

396

async def async_example():

397

model = llm.get_async_model("gpt-4")

398

conversation = model.conversation()

399

400

response = await conversation.prompt("Hello, how are you?")

401

text = await response.text()

402

print(text)

403

404

# Async streaming

405

response = await conversation.prompt("Tell me a joke", stream=True)

406

async for chunk in response:

407

print(chunk, end="", flush=True)

408

409

asyncio.run(async_example())

410

```

411

412

### Attachments and Media

413

414

```python

415

import llm

416

417

model = llm.get_model("gpt-4-vision")

418

419

# File attachment

420

attachment = llm.Attachment(path="/path/to/image.jpg")

421

response = model.prompt("Describe this image", attachments=[attachment])

422

print(response.text())

423

424

# URL attachment

425

attachment = llm.Attachment(url="https://example.com/document.pdf")

426

response = model.prompt("Summarize this document", attachments=[attachment])

427

print(response.text())

428

429

# Binary content

430

with open("data.png", "rb") as f:

431

content = f.read()

432

attachment = llm.Attachment(content=content, type="image/png")

433

response = model.prompt("What's in this image?", attachments=[attachment])

434

print(response.text())

435

```

436

437

### Structured Output

438

439

```python

440

import llm

441

442

model = llm.get_model("gpt-4")

443

444

# Define JSON schema for structured response

445

schema = {

446

"type": "object",

447

"properties": {

448

"name": {"type": "string"},

449

"age": {"type": "number"},

450

"skills": {

451

"type": "array",

452

"items": {"type": "string"}

453

}

454

},

455

"required": ["name", "age"]

456

}

457

458

response = model.prompt(

459

"Create a profile for a software engineer",

460

schema=schema

461

)

462

463

# Get structured JSON response

464

profile = response.response_json()

465

print(f"Name: {profile['name']}")

466

print(f"Age: {profile['age']}")

467

print(f"Skills: {', '.join(profile['skills'])}")

468

```

469

470

This comprehensive models and conversations system provides the foundation for all LLM interactions in the package, supporting both simple prompting and complex multi-turn conversations with rich media and structured outputs.