Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: code interpreter #263

Merged
merged 8 commits into from
Mar 28, 2025
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
53 changes: 53 additions & 0 deletions examples/code_interpreter_demo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
from together import Together

client = Together()

# Create a code interpreter instance
code_interpreter = client.code_interpreter

# Example 1: Simple print statement
print("Example 1: Simple print")
response = code_interpreter.run(code='print("Hello from Together!")', language="python")
print(f"Status: {response.data.status}")
for output in response.data.outputs:
print(f"{output.type}: {output.data}")
if response.data.errors:
print(f"Errors: {response.data.errors}")
print("\n")

# Example 2: Using session for maintaining state
print("Example 2: Using session for state")
response1 = code_interpreter.run(code="x = 42", language="python")
session_id = response1.data.session_id

response2 = code_interpreter.run(
code='print(f"The value of x is {x}")', language="python", session_id=session_id
)
for output in response2.data.outputs:
print(f"{output.type}: {output.data}")
if response2.data.errors:
print(f"Errors: {response2.data.errors}")
print("\n")

# Example 3: More complex computation
print("Example 3: Complex computation")
code = """
!pip install numpy
import numpy as np

# Create a random matrix
matrix = np.random.rand(3, 3)
print("Random matrix:")
print(matrix)

# Calculate eigenvalues
eigenvalues = np.linalg.eigvals(matrix)
print("\\nEigenvalues:")
print(eigenvalues)
"""

response = code_interpreter.run(code=code, language="python")
for output in response.data.outputs:
print(f"{output.type}: {output.data}")
if response.data.errors:
print(f"Errors: {response.data.errors}")
20 changes: 19 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 2 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ build-backend = "poetry.masonry.api"
[tool.poetry]
name = "together"
version = "1.5.3"
authors = [
"Together AI <[email protected]>"
]
authors = ["Together AI <[email protected]>"]
description = "Python client for Together's Cloud Platform!"
readme = "README.md"
license = "Apache-2.0"
Expand Down Expand Up @@ -65,6 +63,7 @@ optional = true
[tool.poetry.group.tests.dependencies]
pytest = ">=7.4.2,<9.0.0"
pytest-watch = "^4.2.0"
pytest-mock = "^3.14.0"
tox = "^4.14.1"

[tool.poetry.group.examples]
Expand Down
5 changes: 5 additions & 0 deletions src/together/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from together import resources
from together.constants import BASE_URL, MAX_RETRIES, TIMEOUT_SECS
from together.error import AuthenticationError
from together.resources.code_interpreter import CodeInterpreter
from together.types import TogetherClient
from together.utils import enforce_trailing_slash
from together.utils.api_helpers import get_google_colab_secret
Expand All @@ -22,6 +23,7 @@ class Together:
fine_tuning: resources.FineTuning
rerank: resources.Rerank
audio: resources.Audio
code_interpreter: CodeInterpreter

# client options
client: TogetherClient
Expand Down Expand Up @@ -87,6 +89,7 @@ def __init__(
self.rerank = resources.Rerank(self.client)
self.audio = resources.Audio(self.client)
self.endpoints = resources.Endpoints(self.client)
self.code_interpreter = CodeInterpreter(self.client)


class AsyncTogether:
Expand All @@ -98,6 +101,7 @@ class AsyncTogether:
models: resources.AsyncModels
fine_tuning: resources.AsyncFineTuning
rerank: resources.AsyncRerank
code_interpreter: CodeInterpreter

# client options
client: TogetherClient
Expand Down Expand Up @@ -161,6 +165,7 @@ def __init__(
self.models = resources.AsyncModels(self.client)
self.fine_tuning = resources.AsyncFineTuning(self.client)
self.rerank = resources.AsyncRerank(self.client)
self.code_interpreter = CodeInterpreter(self.client)


Client = Together
Expand Down
58 changes: 58 additions & 0 deletions src/together/resources/code_interpreter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
from __future__ import annotations

from typing import Dict, Literal, Optional

from together.abstract import api_requestor
from together.together_response import TogetherResponse
from together.types import TogetherClient, TogetherRequest
from together.types.code_interpreter import ExecuteResponse


class CodeInterpreter:
"""Code Interpreter resource for executing code snippets."""

def __init__(self, client: TogetherClient) -> None:
self._client = client

def run(
self,
code: str,
language: Literal["python"],
session_id: Optional[str] = None,
) -> ExecuteResponse:
"""Execute a code snippet.

Args:
code (str): Code snippet to execute
language (str): Programming language for the code to execute. Currently only supports Python.
session_id (str, optional): Identifier of the current session. Used to make follow-up calls.

Returns:
ExecuteResponse: Object containing execution results and outputs
"""
requestor = api_requestor.APIRequestor(
client=self._client,
)

data: Dict[str, str] = {
"code": code,
"language": language,
}

if session_id is not None:
data["session_id"] = session_id

# Use absolute URL to bypass the /v1 prefix
response, _, _ = requestor.request(
options=TogetherRequest(
method="POST",
url="/tci/execute",
params=data,
),
stream=False,
)

assert isinstance(response, TogetherResponse)

# Return the response data directly since our types match the API structure
return ExecuteResponse(**response.data)
46 changes: 46 additions & 0 deletions src/together/types/code_interpreter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
from __future__ import annotations

from typing import Any, Dict, Literal, Union

from pydantic import Field

from together.types.endpoints import TogetherJSONModel


class InterpreterOutput(TogetherJSONModel):
"""Base class for interpreter output types."""

type: Literal["stdout", "stderr", "error", "display_data", "execute_result"] = (
Field(description="The type of output")
)
data: Union[str, Dict[str, Any]] = Field(description="The output data")


class ExecuteResponseData(TogetherJSONModel):
"""Data from code execution response."""

outputs: list[InterpreterOutput] = Field(
description="List of outputs from execution", default_factory=list
)
errors: Union[str, None] = Field(
description="Any errors that occurred during execution", default=None
)
session_id: str = Field(
description="Identifier of the current session. Used to make follow-up calls."
)
status: str = Field(description="Status of the execution", default="completed")


class ExecuteResponse(TogetherJSONModel):
"""Response from code execution."""

data: ExecuteResponseData = Field(
description="The response data containing outputs and session information"
)


__all__ = [
"InterpreterOutput",
"ExecuteResponseData",
"ExecuteResponse",
]
Loading