Skip to content

Commit dd34b7d

Browse files
authored
feat: code interpreter (#263)
* feat: code interpreter * fix base url tests * use v1 route * fix tests * black * add pytest mock * add pytest mock
1 parent e9df12c commit dd34b7d

File tree

7 files changed

+511
-4
lines changed

7 files changed

+511
-4
lines changed

examples/code_interpreter_demo.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
from together import Together
2+
3+
client = Together()
4+
5+
# Create a code interpreter instance
6+
code_interpreter = client.code_interpreter
7+
8+
# Example 1: Simple print statement
9+
print("Example 1: Simple print")
10+
response = code_interpreter.run(code='print("Hello from Together!")', language="python")
11+
print(f"Status: {response.data.status}")
12+
for output in response.data.outputs:
13+
print(f"{output.type}: {output.data}")
14+
if response.data.errors:
15+
print(f"Errors: {response.data.errors}")
16+
print("\n")
17+
18+
# Example 2: Using session for maintaining state
19+
print("Example 2: Using session for state")
20+
response1 = code_interpreter.run(code="x = 42", language="python")
21+
session_id = response1.data.session_id
22+
23+
response2 = code_interpreter.run(
24+
code='print(f"The value of x is {x}")', language="python", session_id=session_id
25+
)
26+
for output in response2.data.outputs:
27+
print(f"{output.type}: {output.data}")
28+
if response2.data.errors:
29+
print(f"Errors: {response2.data.errors}")
30+
print("\n")
31+
32+
# Example 3: More complex computation
33+
print("Example 3: Complex computation")
34+
code = """
35+
!pip install numpy
36+
import numpy as np
37+
38+
# Create a random matrix
39+
matrix = np.random.rand(3, 3)
40+
print("Random matrix:")
41+
print(matrix)
42+
43+
# Calculate eigenvalues
44+
eigenvalues = np.linalg.eigvals(matrix)
45+
print("\\nEigenvalues:")
46+
print(eigenvalues)
47+
"""
48+
49+
response = code_interpreter.run(code=code, language="python")
50+
for output in response.data.outputs:
51+
print(f"{output.type}: {output.data}")
52+
if response.data.errors:
53+
print(f"Errors: {response.data.errors}")

poetry.lock

Lines changed: 19 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@ build-backend = "poetry.masonry.api"
1313
[tool.poetry]
1414
name = "together"
1515
version = "1.5.3"
16-
authors = [
17-
"Together AI <[email protected]>"
18-
]
16+
authors = ["Together AI <[email protected]>"]
1917
description = "Python client for Together's Cloud Platform!"
2018
readme = "README.md"
2119
license = "Apache-2.0"
@@ -65,6 +63,7 @@ optional = true
6563
[tool.poetry.group.tests.dependencies]
6664
pytest = ">=7.4.2,<9.0.0"
6765
pytest-watch = "^4.2.0"
66+
pytest-mock = "^3.14.0"
6867
tox = "^4.14.1"
6968

7069
[tool.poetry.group.examples]

src/together/client.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from together import resources
88
from together.constants import BASE_URL, MAX_RETRIES, TIMEOUT_SECS
99
from together.error import AuthenticationError
10+
from together.resources.code_interpreter import CodeInterpreter
1011
from together.types import TogetherClient
1112
from together.utils import enforce_trailing_slash
1213
from together.utils.api_helpers import get_google_colab_secret
@@ -22,6 +23,7 @@ class Together:
2223
fine_tuning: resources.FineTuning
2324
rerank: resources.Rerank
2425
audio: resources.Audio
26+
code_interpreter: CodeInterpreter
2527

2628
# client options
2729
client: TogetherClient
@@ -87,6 +89,7 @@ def __init__(
8789
self.rerank = resources.Rerank(self.client)
8890
self.audio = resources.Audio(self.client)
8991
self.endpoints = resources.Endpoints(self.client)
92+
self.code_interpreter = CodeInterpreter(self.client)
9093

9194

9295
class AsyncTogether:
@@ -98,6 +101,7 @@ class AsyncTogether:
98101
models: resources.AsyncModels
99102
fine_tuning: resources.AsyncFineTuning
100103
rerank: resources.AsyncRerank
104+
code_interpreter: CodeInterpreter
101105

102106
# client options
103107
client: TogetherClient
@@ -161,6 +165,7 @@ def __init__(
161165
self.models = resources.AsyncModels(self.client)
162166
self.fine_tuning = resources.AsyncFineTuning(self.client)
163167
self.rerank = resources.AsyncRerank(self.client)
168+
self.code_interpreter = CodeInterpreter(self.client)
164169

165170

166171
Client = Together
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
from __future__ import annotations
2+
3+
from typing import Dict, Literal, Optional
4+
5+
from together.abstract import api_requestor
6+
from together.together_response import TogetherResponse
7+
from together.types import TogetherClient, TogetherRequest
8+
from together.types.code_interpreter import ExecuteResponse
9+
10+
11+
class CodeInterpreter:
12+
"""Code Interpreter resource for executing code snippets."""
13+
14+
def __init__(self, client: TogetherClient) -> None:
15+
self._client = client
16+
17+
def run(
18+
self,
19+
code: str,
20+
language: Literal["python"],
21+
session_id: Optional[str] = None,
22+
) -> ExecuteResponse:
23+
"""Execute a code snippet.
24+
25+
Args:
26+
code (str): Code snippet to execute
27+
language (str): Programming language for the code to execute. Currently only supports Python.
28+
session_id (str, optional): Identifier of the current session. Used to make follow-up calls.
29+
30+
Returns:
31+
ExecuteResponse: Object containing execution results and outputs
32+
"""
33+
requestor = api_requestor.APIRequestor(
34+
client=self._client,
35+
)
36+
37+
data: Dict[str, str] = {
38+
"code": code,
39+
"language": language,
40+
}
41+
42+
if session_id is not None:
43+
data["session_id"] = session_id
44+
45+
# Use absolute URL to bypass the /v1 prefix
46+
response, _, _ = requestor.request(
47+
options=TogetherRequest(
48+
method="POST",
49+
url="/tci/execute",
50+
params=data,
51+
),
52+
stream=False,
53+
)
54+
55+
assert isinstance(response, TogetherResponse)
56+
57+
# Return the response data directly since our types match the API structure
58+
return ExecuteResponse(**response.data)
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
from __future__ import annotations
2+
3+
from typing import Any, Dict, Literal, Union
4+
5+
from pydantic import Field
6+
7+
from together.types.endpoints import TogetherJSONModel
8+
9+
10+
class InterpreterOutput(TogetherJSONModel):
11+
"""Base class for interpreter output types."""
12+
13+
type: Literal["stdout", "stderr", "error", "display_data", "execute_result"] = (
14+
Field(description="The type of output")
15+
)
16+
data: Union[str, Dict[str, Any]] = Field(description="The output data")
17+
18+
19+
class ExecuteResponseData(TogetherJSONModel):
20+
"""Data from code execution response."""
21+
22+
outputs: list[InterpreterOutput] = Field(
23+
description="List of outputs from execution", default_factory=list
24+
)
25+
errors: Union[str, None] = Field(
26+
description="Any errors that occurred during execution", default=None
27+
)
28+
session_id: str = Field(
29+
description="Identifier of the current session. Used to make follow-up calls."
30+
)
31+
status: str = Field(description="Status of the execution", default="completed")
32+
33+
34+
class ExecuteResponse(TogetherJSONModel):
35+
"""Response from code execution."""
36+
37+
data: ExecuteResponseData = Field(
38+
description="The response data containing outputs and session information"
39+
)
40+
41+
42+
__all__ = [
43+
"InterpreterOutput",
44+
"ExecuteResponseData",
45+
"ExecuteResponse",
46+
]

0 commit comments

Comments
 (0)