Skip to content

Commit 9575417

Browse files
committed
Fix code interpreter
1 parent 5d278dc commit 9575417

File tree

3 files changed

+44
-28
lines changed

3 files changed

+44
-28
lines changed

llmstack/apps/apis.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -844,7 +844,7 @@ async def get_app_runner_async(self, session_id, source, request_user, input_dat
844844
input_schema = json.loads(processor_cls.get_input_schema())
845845
input_fields = []
846846
for property in input_schema["properties"]:
847-
input_fields.append({"name": property, "type": input_schema["properties"][property]["type"]})
847+
input_fields.append({"name": property, "type": input_schema["properties"][property].get("type", "string")})
848848

849849
app_data = {
850850
"name": f"Processor {provider_slug}_{processor_slug}",

llmstack/play/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ def _done_callback(future):
8686
except CancelledError:
8787
logger.info("Task cancelled")
8888
except Exception as e:
89-
logger.error(f"Task in loop {name} failed with error: {e}")
89+
logger.exception(f"Task in loop {name} failed with error: {e}")
9090
finally:
9191
# Find and cancel all pending tasks before stopping the loop
9292
for task in asyncio.all_tasks(loop):

llmstack/processors/providers/promptly/code_interpreter.py

Lines changed: 42 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
import base64
22
import logging
33
import uuid
4-
from typing import Dict, List, Optional
4+
from typing import List, Optional
55

6-
import grpc
76
from asgiref.sync import async_to_sync
87
from django.conf import settings
8+
from langrocks.client.code_runner import (
9+
CodeRunner,
10+
CodeRunnerSession,
11+
CodeRunnerState,
12+
Content,
13+
ContentMimeType,
14+
)
915
from pydantic import Field
1016

1117
from llmstack.apps.schemas import OutputTemplate
@@ -14,7 +20,10 @@
1420
ApiProcessorInterface,
1521
ApiProcessorSchema,
1622
)
17-
from llmstack.processors.providers.promptly import Content, ContentMimeType
23+
from llmstack.processors.providers.promptly import Content as PromptlyContent
24+
from llmstack.processors.providers.promptly import (
25+
ContentMimeType as PromptlyContentMimeType,
26+
)
1827

1928
logger = logging.getLogger(__name__)
2029

@@ -25,15 +34,21 @@ class CodeInterpreterLanguage(StrEnum):
2534

2635
class CodeInterpreterInput(ApiProcessorSchema):
2736
code: str = Field(description="The code to run", json_schema_extra={"widget": "textarea"}, default="")
37+
files: Optional[str] = Field(
38+
description="Workspace files as a comma separated list",
39+
default=None,
40+
json_schema_extra={
41+
"widget": "file",
42+
},
43+
)
2844
language: CodeInterpreterLanguage = Field(
2945
title="Language", description="The language of the code", default=CodeInterpreterLanguage.PYTHON
3046
)
3147

3248

3349
class CodeInterpreterOutput(ApiProcessorSchema):
34-
stdout: List[Content] = Field(default=[], description="Standard output as a list of Content objects")
50+
stdout: List[PromptlyContent] = Field(default=[], description="Standard output as a list of Content objects")
3551
stderr: str = Field(default="", description="Standard error")
36-
local_variables: Optional[Dict] = Field(description="Local variables as a JSON object")
3752
exit_code: int = Field(default=0, description="Exit code of the process")
3853

3954

@@ -106,33 +121,34 @@ def convert_stdout_to_content(self, stdout) -> List[Content]:
106121
return content
107122

108123
def process_session_data(self, session_data):
109-
self._kernel_session_id = session_data.get("kernel_session_id", None)
124+
self._interpreter_session_id = session_data.get("interpreter_session_id", str(uuid.uuid4()))
125+
self._interpreter_session_data = session_data.get("interpreter_session_data", "")
110126

111127
def session_data_to_persist(self) -> dict:
112128
return {
113-
"kernel_session_id": self._kernel_session_id,
129+
"interpreter_session_id": self._interpreter_session_id,
130+
"interpreter_session_data": self._interpreter_session_data,
114131
}
115132

116133
def process(self) -> dict:
117-
from langrocks.common.models import runner_pb2, runner_pb2_grpc
118-
119-
kernel_session_id = self._kernel_session_id if self._kernel_session_id else str(uuid.uuid4())
120-
121-
channel = grpc.insecure_channel(f"{settings.RUNNER_HOST}:{settings.RUNNER_PORT}")
122-
stub = runner_pb2_grpc.RunnerStub(channel)
123-
124-
request = runner_pb2.CodeRunnerRequest(source_code=self._input.code, timeout_secs=self._config.timeout)
125-
response_iter = stub.GetCodeRunner(
126-
iter([request]),
127-
metadata=(("kernel_session_id", kernel_session_id),),
128-
)
129-
for response in response_iter:
130-
if response.stdout:
131-
stdout_result = self.convert_stdout_to_content(response.stdout)
132-
async_to_sync(self._output_stream.write)(CodeInterpreterOutput(stdout=stdout_result))
133-
134-
if response.stderr:
135-
async_to_sync(self._output_stream.write)(CodeInterpreterOutput(stderr=response.stderr))
134+
with CodeRunner(
135+
base_url=f"{settings.RUNNER_HOST}:{settings.RUNNER_PORT}",
136+
session=CodeRunnerSession(
137+
session_id=self._interpreter_session_id, session_data=self._interpreter_session_data
138+
),
139+
) as code_runner:
140+
current_state = code_runner.get_state()
141+
if current_state == CodeRunnerState.CODE_RUNNING:
142+
respose_iter = code_runner.run_code(source_code=self._input.code)
143+
for response in respose_iter:
144+
async_to_sync(self._output_stream.write)(
145+
CodeInterpreterOutput(
146+
stdout=[PromptlyContent(mime_type=PromptlyContentMimeType.TEXT, data=response.decode())]
147+
)
148+
)
149+
150+
session_data = code_runner.get_session()
151+
self._interpreter_session_data = session_data.session_data
136152

137153
output = self._output_stream.finalize()
138154
return output

0 commit comments

Comments
 (0)