Skip to content

Commit 130e159

Browse files
authored
Merge branch 'main' into doug/engine-stamped-request-ids
2 parents 2d6423f + 0abbe43 commit 130e159

File tree

7 files changed

+677
-2
lines changed

7 files changed

+677
-2
lines changed

src/steamship/__init__.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,24 @@
3434

3535
from .client import Steamship # isort:skip
3636

37+
SUPPORTED_PYTHON_VERSIONS = [(3, 10)]
38+
SUPPORTED_PYTHON_VERSION_NAMES = [f"{major}.{minor}" for major, minor in SUPPORTED_PYTHON_VERSIONS]
39+
40+
41+
def is_supported_python_version() -> bool:
42+
import sys
43+
44+
major, minor, _, _, _ = sys.version_info
45+
for supported_version in SUPPORTED_PYTHON_VERSIONS:
46+
s_major, s_minor = supported_version
47+
supported = (major == s_major) and (s_minor is None or s_minor == minor)
48+
if supported:
49+
break
50+
else:
51+
return False
52+
return True
53+
54+
3755
__all__ = [
3856
"Steamship",
3957
"Configuration",
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import logging
2+
from pprint import pformat
3+
from typing import List, Optional
4+
5+
from steamship import Block, File, MimeTypes, PluginInstance, Steamship, SteamshipError, Tag
6+
from steamship.data import GenerationTag, TagKind
7+
from steamship.plugin.capabilities import (
8+
Capability,
9+
CapabilityPluginRequest,
10+
CapabilityPluginResponse,
11+
)
12+
13+
14+
class SteamshipLLM:
15+
"""A class wrapping LLM plugins."""
16+
17+
def __init__(self, plugin_instance: PluginInstance):
18+
self.client = plugin_instance.client
19+
self.plugin_instance = plugin_instance
20+
21+
class Impls:
22+
@staticmethod
23+
def gpt(
24+
client: Steamship,
25+
plugin_version: Optional[str] = None,
26+
model: str = "gpt-4",
27+
temperature: float = 0.4,
28+
max_tokens: int = 256,
29+
**kwargs,
30+
):
31+
gpt = client.use_plugin(
32+
"gpt-4",
33+
version=plugin_version,
34+
config={
35+
"model": model,
36+
"temperature": temperature,
37+
"max_tokens": max_tokens,
38+
**kwargs,
39+
},
40+
)
41+
return SteamshipLLM(gpt)
42+
43+
def generate(
44+
self,
45+
messages: List[Block],
46+
capabilities: List[Capability] = None,
47+
assert_capabilities: bool = True,
48+
**kwargs,
49+
) -> List[Block]:
50+
"""
51+
Call the LLM plugin's generate method. Generate requests for plugin capabilities based on input parameters.
52+
53+
:param messages: Messages to be passed to the LLM to construct the prompt.
54+
:param capabilities: Capabilities that will be asked of the LLM. See the docstring for
55+
steamship.plugins.capabilities.
56+
57+
If default_capabilities was provided at construction, those capabilities will be requested unless overridden
58+
by this parameter.
59+
:param assert_capabilities: If True (default), raise a SteamshipError if the LLM plugin did not respond with a
60+
block that asserts what level capabilities were fulfilled at.
61+
:param kwargs: Options that can be passed to the LLM model as other parameters.
62+
:return: a List of Blocks that are returned from the plugin.
63+
"""
64+
file_ids = {b.file_id for b in messages}
65+
block_ids = None
66+
temp_file = None
67+
if len(file_ids) != 1 and next(iter(file_ids)) is not None:
68+
file_id = next(iter(file_ids))
69+
block_ids = [b.id for b in messages]
70+
else:
71+
temp_file = File.create(
72+
client=self.client,
73+
blocks=messages,
74+
tags=[Tag(kind=TagKind.GENERATION, name=GenerationTag.PROMPT_COMPLETION)],
75+
)
76+
file_id = temp_file.id
77+
78+
request_block = CapabilityPluginRequest(requested_capabilities=capabilities).create_block(
79+
client=self.client, file_id=file_id
80+
)
81+
if block_ids:
82+
block_ids.append(request_block.id)
83+
84+
try:
85+
generation_task = self.plugin_instance.generate(
86+
input_file_id=file_id, input_file_block_index_list=block_ids, options=kwargs
87+
)
88+
generation_task.wait()
89+
90+
for block in generation_task.output.blocks:
91+
if block.mime_type == MimeTypes.STEAMSHIP_PLUGIN_CAPABILITIES_RESPONSE:
92+
if logging.DEBUG >= logging.root.getEffectiveLevel():
93+
response = CapabilityPluginResponse.from_block(block)
94+
logging.debug(
95+
f"Plugin capability fulfillment:\n\n{pformat(response.json())}"
96+
)
97+
break
98+
else:
99+
if assert_capabilities:
100+
version_string = f"{self.plugin_instance.plugin_handle}, v.{self.plugin_instance.plugin_version_handle}"
101+
raise SteamshipError(
102+
f"Asserting capabilities are used, but capability response was not returned by plugin ({version_string})"
103+
)
104+
finally:
105+
if temp_file:
106+
temp_file.delete()
107+
108+
return generation_task.output.blocks

src/steamship/base/mime_types.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from enum import Enum
22

3+
STEAMSHIP_PREFIX = "application/vnd.steamship-block"
4+
35

46
class MimeTypes(str, Enum):
57
UNKNOWN = "unknown"
@@ -19,7 +21,7 @@ class MimeTypes(str, Enum):
1921
PPTX = "application/vnd.openxmlformats-officedocument.presentationml.presentation"
2022
RTF = "application/rtf"
2123
BINARY = "application/octet-stream"
22-
STEAMSHIP_BLOCK_JSON = "application/vnd.steamship-block.json.v1"
24+
STEAMSHIP_BLOCK_JSON = f"{STEAMSHIP_PREFIX}.json.v1"
2325
WAV = "audio/wav"
2426
MP3 = "audio/mp3"
2527
OGG_AUDIO = "audio/ogg"
@@ -30,6 +32,17 @@ class MimeTypes(str, Enum):
3032
WEBM_AUDIO = "audio/webm"
3133
FILE_JSON = "fileJson"
3234

35+
# This block contains information that isn't part of the payload to/from a plugin, but instead is json-formatted
36+
# information about if/how the plugin supports certain behaviors.
37+
STEAMSHIP_PLUGIN_CAPABILITIES_REQUEST = f"{STEAMSHIP_PREFIX}.plugin-capabilities-request+json"
38+
STEAMSHIP_PLUGIN_CAPABILITIES_RESPONSE = f"{STEAMSHIP_PREFIX}.plugin-capabilities-response+json"
39+
STEAMSHIP_PLUGIN_FUNCTION_CALL_INVOCATION = (
40+
f"{STEAMSHIP_PREFIX}.function-calling-support-invocation+json"
41+
)
42+
STEAMSHIP_PLUGIN_FUNCTION_CALL_RESULT = (
43+
f"{STEAMSHIP_PREFIX}.function-calling-support-result+json"
44+
)
45+
3346
@classmethod
3447
def has_value(cls, value):
3548
return value in cls._value2member_map_

src/steamship/cli/cli.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,16 @@
4141

4242
@click.group()
4343
def cli():
44-
pass
44+
if not steamship.is_supported_python_version():
45+
click.echo("⚠️ ⚠️ ⚠️️️️️️️️️️️")
46+
click.echo(f"Running on unsupported Python version: {sys.version}")
47+
click.echo(
48+
"Steamship runtime supports only the following versions; you may see irregular behavior otherwise:"
49+
)
50+
for supported_name in steamship.SUPPORTED_PYTHON_VERSION_NAMES:
51+
click.echo(f" {supported_name}")
52+
click.echo("Please develop against supported Python versions.")
53+
click.echo("⚠️ ⚠️ ⚠️️️️️️️️️️️")
4554

4655

4756
def initialize(suppress_message: bool = False):

src/steamship/data/block.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
from steamship import MimeTypes, SteamshipError
1010
from steamship.base.client import Client
11+
from steamship.base.mime_types import STEAMSHIP_PREFIX
1112
from steamship.base.model import CamelModel
1213
from steamship.base.request import DeleteRequest, IdentifierRequest, Request
1314
from steamship.base.response import Response
@@ -218,6 +219,9 @@ def is_audio(self):
218219
MimeTypes.OGG_AUDIO,
219220
]
220221

222+
def is_steamship_internal(self):
223+
return self.mime_type.startswith(STEAMSHIP_PREFIX)
224+
221225
def is_video(self):
222226
"""Return whether this is a video Block."""
223227
return self.mime_type in [MimeTypes.MP4_VIDEO, MimeTypes.WEBM_VIDEO, MimeTypes.OGG_VIDEO]

0 commit comments

Comments
 (0)