Skip to content

Commit 735b323

Browse files
douglas-reidDouglas Reideob
authored
refactor: cleanup agent class objects (#384)
This PR represents an attempt to cleanup, document, and rationalize the existing set of classes in `agent` hierarchy. I also wanted to remove as much vestigial and unused surface (primarily related to async execution) in an attempt to simplify and reduce surface area for implementors. As part of this PR, I updated the example assistant to show how synchronous agent responses could be done using `emitFns`. This then led to an update of the REPL to allow flexible identification of `AgentService` methods. I think we need more thought there. Because we've introduced an `LLM` class, I took the `get_llm()` method that created ad-hoc ones from context off of the context and added helpers to create contexts with LLM instances. This was an attempt to rationalize usage within Tools, etc. I'm open to other approaches there. --------- Co-authored-by: Douglas Reid <doug@steamship.com> Co-authored-by: Ted Benson <ted@steamship.com>
1 parent cc4dda3 commit 735b323

54 files changed

Lines changed: 513 additions & 550 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/steamship/agents/base.py

Lines changed: 0 additions & 64 deletions
This file was deleted.

src/steamship/agents/context/context.py

Lines changed: 0 additions & 99 deletions
This file was deleted.

src/steamship/agents/example_agents/my_assistant.py

Lines changed: 0 additions & 64 deletions
This file was deleted.
File renamed without changes.
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import uuid
2+
from typing import List
3+
4+
from steamship import Block
5+
from steamship.agents.llms.openai import OpenAI
6+
from steamship.agents.react import ReACTAgent
7+
from steamship.agents.schema import AgentContext
8+
from steamship.agents.schema.context import Metadata
9+
from steamship.agents.service.agent_service import AgentService
10+
from steamship.agents.tools.image_generation.dalle import DalleTool
11+
from steamship.agents.tools.search.search import SearchTool
12+
from steamship.invocable import post
13+
from steamship.utils.repl import AgentREPL
14+
15+
16+
class MyAssistant(AgentService):
17+
def __init__(self, **kwargs):
18+
super().__init__(**kwargs)
19+
self._agent = ReACTAgent(
20+
tools=[
21+
SearchTool(),
22+
DalleTool(),
23+
],
24+
llm=OpenAI(self.client),
25+
)
26+
27+
@post("prompt")
28+
def prompt(self, prompt: str) -> str:
29+
context_id = uuid.uuid4()
30+
context = AgentContext.get_or_create(self.client, {"id": f"{context_id}"})
31+
context.chat_history.append_user_message(prompt)
32+
33+
# TODO: is this preferred over taking the last step in completed step?
34+
output = ""
35+
36+
def sync_emit(blocks: List[Block], meta: Metadata):
37+
nonlocal output
38+
block_text = "\n".join([b.text for b in blocks if b.is_text()])
39+
output += block_text
40+
41+
context.emit_funcs.append(sync_emit)
42+
self.run_agent(self._agent, context)
43+
return output
44+
45+
46+
if __name__ == "__main__":
47+
AgentREPL(MyAssistant, "prompt").run()

src/steamship/agents/llm/__init__.py

Whitespace-only changes.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from .openai import OpenAI
2+
3+
__all__ = ["OpenAI"]
Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
1-
from typing import List
1+
from typing import List, Optional
22

33
from steamship import Block, PluginInstance, Steamship
4-
from steamship.agents.base import LLM
4+
from steamship.agents.schema import LLM
55

66
PLUGIN_HANDLE = "gpt-4"
77

88

99
class OpenAI(LLM):
10+
"""LLM that uses Steamship's OpenAI plugin to generate completions.
11+
12+
NOTE: By default, this LLM uses the `gpt-3.5-turbo` model. Valid model
13+
choices are `gpt-3.5-turbo` and `gpt-4`.
14+
"""
15+
1016
generator: PluginInstance
1117
client: Steamship
1218

@@ -21,7 +27,10 @@ def __init__(self, client, model_name: str = "gpt-3.5-turbo", *args, **kwargs):
2127
generator = client.use_plugin(PLUGIN_HANDLE, config={"model": model_name})
2228
super().__init__(client=client, generator=generator, *args, **kwargs)
2329

24-
def complete(self, prompt: str, stop: str) -> List[Block]:
25-
action_task = self.generator.generate(text=prompt, options={"stop": stop})
30+
def complete(self, prompt: str, stop: Optional[str] = None) -> List[Block]:
31+
options = {}
32+
if stop:
33+
options["stop"] = stop
34+
action_task = self.generator.generate(text=prompt, options=options)
2635
action_task.wait()
2736
return action_task.output.blocks
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from .chathistory import ChatHistory
2+
3+
__all__ = ["ChatHistory"]

src/steamship/agents/context/chathistory.py renamed to src/steamship/agents/memory/chathistory.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def __init__(self, file: File):
2121

2222
@staticmethod
2323
def _get_existing_file(client: Client, context_keys: Dict[str, str]) -> Optional[File]:
24-
"""Find an existing File object whose context Tag matches the passed context keys"""
24+
"""Find an existing File object whose memory Tag matches the passed memory keys"""
2525
file_query = " and ".join(
2626
[f'value("{key}") = "{value}"' for key, value in context_keys.items()]
2727
)
@@ -32,7 +32,7 @@ def _get_existing_file(client: Client, context_keys: Dict[str, str]) -> Optional
3232
return None
3333
else:
3434
raise SteamshipError(
35-
"Multiple ChatHistory objects have been created in this workspace with these context keys."
35+
"Multiple ChatHistory objects have been created in this workspace with these memory keys."
3636
)
3737

3838
@staticmethod
@@ -48,6 +48,7 @@ def get_or_create(
4848
tags = tags or []
4949
tags.append(Tag(kind=TagKind.DOCUMENT, name=DocTag.CHAT))
5050
tags.append(Tag(kind=TagKind.CHAT, name=ChatTag.CONTEXT_KEYS, value=context_keys))
51+
5152
blocks = []
5253
file = File.create(
5354
client=client,

0 commit comments

Comments
 (0)