prompty 0.1.9__py3-none-any.whl → 0.1.33__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,10 @@
1
+ # __init__.py
2
+ from prompty.invoker import InvokerException
3
+
4
+ try:
5
+ from .executor import OpenAIExecutor
6
+ from .processor import OpenAIProcessor
7
+ except ImportError:
8
+ raise InvokerException(
9
+ "Error registering OpenAIExecutor and OpenAIProcessor", "openai"
10
+ )
@@ -0,0 +1,114 @@
1
+ import importlib.metadata
2
+ from openai import OpenAI
3
+ from typing import Iterator
4
+
5
+ from prompty.tracer import Tracer
6
+ from ..core import Prompty, PromptyStream
7
+ from ..invoker import Invoker, InvokerFactory
8
+
9
+ VERSION = importlib.metadata.version("prompty")
10
+
11
+
12
+ @InvokerFactory.register_executor("openai")
13
+ class OpenAIExecutor(Invoker):
14
+ """OpenAI Executor"""
15
+
16
+ def __init__(self, prompty: Prompty) -> None:
17
+ super().__init__(prompty)
18
+ self.kwargs = {
19
+ key: value
20
+ for key, value in self.prompty.model.configuration.items()
21
+ if key != "type"
22
+ }
23
+
24
+ self.api = self.prompty.model.api
25
+ self.deployment = self.prompty.model.configuration["azure_deployment"]
26
+ self.parameters = self.prompty.model.parameters
27
+
28
+ def invoke(self, data: any) -> any:
29
+ """Invoke the OpenAI API
30
+
31
+ Parameters
32
+ ----------
33
+ data : any
34
+ The data to send to the OpenAI API
35
+
36
+ Returns
37
+ -------
38
+ any
39
+ The response from the OpenAI API
40
+ """
41
+ with Tracer.start("OpenAI") as trace:
42
+ trace("type", "LLM")
43
+ trace("signature", "OpenAI.ctor")
44
+ trace("description", "OpenAI Constructor")
45
+ trace("inputs", self.kwargs)
46
+ client = OpenAI(
47
+ default_headers={
48
+ "User-Agent": f"prompty/{VERSION}",
49
+ "x-ms-useragent": f"prompty/{VERSION}",
50
+ },
51
+ **self.kwargs,
52
+ )
53
+ trace("result", client)
54
+
55
+ with Tracer.start("create") as trace:
56
+ trace("type", "LLM")
57
+ trace("description", "OpenAI Prompty Execution Invoker")
58
+
59
+ if self.api == "chat":
60
+ trace("signature", "OpenAI.chat.completions.create")
61
+ args = {
62
+ "model": self.deployment,
63
+ "messages": data if isinstance(data, list) else [data],
64
+ **self.parameters,
65
+ }
66
+ trace("inputs", args)
67
+ response = client.chat.completions.create(**args)
68
+
69
+ elif self.api == "completion":
70
+ trace("signature", "OpenAI.completions.create")
71
+ args = {
72
+ "prompt": data.item,
73
+ "model": self.deployment,
74
+ **self.parameters,
75
+ }
76
+ trace("inputs", args)
77
+ response = client.completions.create(**args)
78
+
79
+ elif self.api == "embedding":
80
+ trace("signature", "OpenAI.embeddings.create")
81
+ args = {
82
+ "input": data if isinstance(data, list) else [data],
83
+ "model": self.deployment,
84
+ **self.parameters,
85
+ }
86
+ trace("inputs", args)
87
+ response = client.embeddings.create(**args)
88
+
89
+ elif self.api == "image":
90
+ raise NotImplementedError("OpenAI Image API is not implemented yet")
91
+
92
+ # stream response
93
+ if isinstance(response, Iterator):
94
+ stream = PromptyStream("AzureOpenAIExecutor", response)
95
+ trace("result", stream)
96
+ return stream
97
+ else:
98
+ trace("result", response)
99
+ return response
100
+
101
+ async def invoke_async(self, data: str) -> str:
102
+ """Invoke the Prompty Chat Parser (Async)
103
+
104
+ Parameters
105
+ ----------
106
+ data : str
107
+ The data to parse
108
+
109
+ Returns
110
+ -------
111
+ str
112
+ The parsed data
113
+ """
114
+ return self.invoke(data)
@@ -1,38 +1,30 @@
1
1
  from typing import Iterator
2
- from pydantic import BaseModel
3
2
  from openai.types.completion import Completion
4
3
  from openai.types.chat.chat_completion import ChatCompletion
5
- from .core import Invoker, InvokerFactory, Prompty, PromptyStream
4
+ from ..invoker import Invoker, InvokerFactory
5
+ from ..core import Prompty, PromptyStream, ToolCall
6
6
  from openai.types.create_embedding_response import CreateEmbeddingResponse
7
7
 
8
8
 
9
- class ToolCall(BaseModel):
10
- id: str
11
- name: str
12
- arguments: str
13
-
14
-
15
9
  @InvokerFactory.register_processor("openai")
16
- @InvokerFactory.register_processor("azure")
17
- @InvokerFactory.register_processor("azure_openai")
18
10
  class OpenAIProcessor(Invoker):
19
- """OpenAI/Azure Processor"""
11
+ """OpenAI Processor"""
20
12
 
21
13
  def __init__(self, prompty: Prompty) -> None:
22
14
  super().__init__(prompty)
23
15
 
24
16
  def invoke(self, data: any) -> any:
25
- """Invoke the OpenAI/Azure API
17
+ """Invoke the OpenAI API
26
18
 
27
19
  Parameters
28
20
  ----------
29
21
  data : any
30
- The data to send to the OpenAI/Azure API
22
+ The data to send to the OpenAI API
31
23
 
32
24
  Returns
33
25
  -------
34
26
  any
35
- The response from the OpenAI/Azure API
27
+ The response from the OpenAI API
36
28
  """
37
29
  if isinstance(data, ChatCompletion):
38
30
  response = data.choices[0].message
@@ -62,10 +54,28 @@ class OpenAIProcessor(Invoker):
62
54
 
63
55
  def generator():
64
56
  for chunk in data:
65
- if len(chunk.choices) == 1 and chunk.choices[0].delta.content != None:
57
+ if (
58
+ len(chunk.choices) == 1
59
+ and chunk.choices[0].delta.content != None
60
+ ):
66
61
  content = chunk.choices[0].delta.content
67
62
  yield content
68
63
 
69
64
  return PromptyStream("OpenAIProcessor", generator())
70
65
  else:
71
66
  return data
67
+
68
+ async def invoke_async(self, data: str) -> str:
69
+ """Invoke the Prompty Chat Parser (Async)
70
+
71
+ Parameters
72
+ ----------
73
+ data : str
74
+ The data to parse
75
+
76
+ Returns
77
+ -------
78
+ str
79
+ The parsed data
80
+ """
81
+ return self.invoke(data)
prompty/parsers.py CHANGED
@@ -1,6 +1,7 @@
1
1
  import re
2
2
  import base64
3
- from .core import Invoker, InvokerFactory, Prompty
3
+ from .core import Prompty
4
+ from .invoker import Invoker, InvokerFactory
4
5
 
5
6
 
6
7
  @InvokerFactory.register_parser("prompty.chat")
@@ -137,3 +138,19 @@ class PromptyChatParser(Invoker):
137
138
  messages.append({"role": role, "content": self.parse_content(content)})
138
139
 
139
140
  return messages
141
+
142
+
143
+ async def invoke_async(self, data: str) -> str:
144
+ """ Invoke the Prompty Chat Parser (Async)
145
+
146
+ Parameters
147
+ ----------
148
+ data : str
149
+ The data to parse
150
+
151
+ Returns
152
+ -------
153
+ str
154
+ The parsed data
155
+ """
156
+ return self.invoke(data)
prompty/renderers.py CHANGED
@@ -1,10 +1,12 @@
1
+ from .core import Prompty
1
2
  from jinja2 import DictLoader, Environment
2
- from .core import Invoker, InvokerFactory, Prompty
3
+ from .invoker import Invoker, InvokerFactory
3
4
 
4
5
 
5
6
  @InvokerFactory.register_renderer("jinja2")
6
7
  class Jinja2Renderer(Invoker):
7
- """ Jinja2 Renderer """
8
+ """Jinja2 Renderer"""
9
+
8
10
  def __init__(self, prompty: Prompty) -> None:
9
11
  super().__init__(prompty)
10
12
  self.templates = {}
@@ -21,3 +23,18 @@ class Jinja2Renderer(Invoker):
21
23
  t = env.get_template(self.name)
22
24
  generated = t.render(**data)
23
25
  return generated
26
+
27
+ async def invoke_async(self, data: str) -> str:
28
+ """Invoke the Prompty Chat Parser (Async)
29
+
30
+ Parameters
31
+ ----------
32
+ data : str
33
+ The data to parse
34
+
35
+ Returns
36
+ -------
37
+ str
38
+ The parsed data
39
+ """
40
+ return self.invoke(data)
@@ -0,0 +1,8 @@
1
+ # __init__.py
2
+ from prompty.invoker import InvokerException
3
+
4
+ try:
5
+ from .executor import ServerlessExecutor
6
+ from .processor import ServerlessProcessor
7
+ except ImportError:
8
+ raise InvokerException("Error registering ServerlessExecutor and ServerlessProcessor", "serverless")
@@ -0,0 +1,153 @@
1
+ import importlib.metadata
2
+ from typing import Iterator
3
+ from azure.core.credentials import AzureKeyCredential
4
+ from azure.ai.inference import (
5
+ ChatCompletionsClient,
6
+ EmbeddingsClient,
7
+ )
8
+ from azure.ai.inference.models import (
9
+ StreamingChatCompletions,
10
+ AsyncStreamingChatCompletions,
11
+ )
12
+
13
+ from ..tracer import Tracer
14
+ from ..invoker import Invoker, InvokerFactory
15
+ from ..core import Prompty, PromptyStream, AsyncPromptyStream
16
+
17
+ VERSION = importlib.metadata.version("prompty")
18
+
19
+
20
+ @InvokerFactory.register_executor("serverless")
21
+ class ServerlessExecutor(Invoker):
22
+ """Azure OpenAI Executor"""
23
+
24
+ def __init__(self, prompty: Prompty) -> None:
25
+ super().__init__(prompty)
26
+
27
+ # serverless configuration
28
+ self.endpoint = self.prompty.model.configuration["endpoint"]
29
+ self.model = self.prompty.model.configuration["model"]
30
+ self.key = self.prompty.model.configuration["key"]
31
+
32
+ # api type
33
+ self.api = self.prompty.model.api
34
+
35
+ def _response(self, response: any) -> any:
36
+ # stream response
37
+ if isinstance(response, Iterator):
38
+ if isinstance(response, StreamingChatCompletions):
39
+ stream = PromptyStream("ServerlessExecutor", response)
40
+ return stream
41
+ elif isinstance(response, AsyncStreamingChatCompletions):
42
+ stream = AsyncPromptyStream("ServerlessExecutor", response)
43
+ return stream
44
+ else:
45
+ stream = PromptyStream("ServerlessExecutor", response)
46
+
47
+ return stream
48
+ else:
49
+ return response
50
+
51
+ def invoke(self, data: any) -> any:
52
+ """Invoke the Serverless SDK
53
+
54
+ Parameters
55
+ ----------
56
+ data : any
57
+ The data to send to the Serverless SDK
58
+
59
+ Returns
60
+ -------
61
+ any
62
+ The response from the Serverless SDK
63
+ """
64
+
65
+ cargs = {
66
+ "endpoint": self.endpoint,
67
+ "credential": AzureKeyCredential(self.key),
68
+ }
69
+
70
+ if self.api == "chat":
71
+ with Tracer.start("ChatCompletionsClient") as trace:
72
+ trace("type", "LLM")
73
+ trace("signature", "azure.ai.inference.ChatCompletionsClient.ctor")
74
+ trace(
75
+ "description", "Azure Unified Inference SDK Chat Completions Client"
76
+ )
77
+ trace("inputs", cargs)
78
+ client = ChatCompletionsClient(
79
+ user_agent=f"prompty/{VERSION}",
80
+ **cargs,
81
+ )
82
+ trace("result", client)
83
+
84
+ with Tracer.start("complete") as trace:
85
+ trace("type", "LLM")
86
+ trace("signature", "azure.ai.inference.ChatCompletionsClient.complete")
87
+ trace(
88
+ "description", "Azure Unified Inference SDK Chat Completions Client"
89
+ )
90
+ eargs = {
91
+ "model": self.model,
92
+ "messages": data if isinstance(data, list) else [data],
93
+ **self.prompty.model.parameters,
94
+ }
95
+ trace("inputs", eargs)
96
+ r = client.complete(**eargs)
97
+ trace("result", r)
98
+
99
+ response = self._response(r)
100
+
101
+ elif self.api == "completion":
102
+ raise NotImplementedError(
103
+ "Serverless Completions API is not implemented yet"
104
+ )
105
+
106
+ elif self.api == "embedding":
107
+ with Tracer.start("EmbeddingsClient") as trace:
108
+ trace("type", "LLM")
109
+ trace("signature", "azure.ai.inference.EmbeddingsClient.ctor")
110
+ trace("description", "Azure Unified Inference SDK Embeddings Client")
111
+ trace("inputs", cargs)
112
+ client = EmbeddingsClient(
113
+ user_agent=f"prompty/{VERSION}",
114
+ **cargs,
115
+ )
116
+ trace("result", client)
117
+
118
+ with Tracer.start("complete") as trace:
119
+ trace("type", "LLM")
120
+ trace("signature", "azure.ai.inference.ChatCompletionsClient.complete")
121
+ trace(
122
+ "description", "Azure Unified Inference SDK Chat Completions Client"
123
+ )
124
+ eargs = {
125
+ "model": self.model,
126
+ "input": data if isinstance(data, list) else [data],
127
+ **self.prompty.model.parameters,
128
+ }
129
+ trace("inputs", eargs)
130
+ r = client.complete(**eargs)
131
+ trace("result", r)
132
+
133
+ response = self._response(r)
134
+
135
+ elif self.api == "image":
136
+ raise NotImplementedError("Azure OpenAI Image API is not implemented yet")
137
+
138
+ return response
139
+
140
+ async def invoke_async(self, data: str) -> str:
141
+ """Invoke the Prompty Chat Parser (Async)
142
+
143
+ Parameters
144
+ ----------
145
+ data : str
146
+ The data to parse
147
+
148
+ Returns
149
+ -------
150
+ str
151
+ The parsed data
152
+ """
153
+ return self.invoke(data)
@@ -0,0 +1,78 @@
1
+ from typing import Iterator
2
+ from ..invoker import Invoker, InvokerFactory
3
+ from ..core import Prompty, PromptyStream, ToolCall
4
+
5
+ from azure.ai.inference.models import ChatCompletions, EmbeddingsResult
6
+
7
+
8
+ @InvokerFactory.register_processor("serverless")
9
+ class ServerlessProcessor(Invoker):
10
+ """OpenAI Processor"""
11
+
12
+ def __init__(self, prompty: Prompty) -> None:
13
+ super().__init__(prompty)
14
+
15
+ def invoke(self, data: any) -> any:
16
+ """Invoke the OpenAI API
17
+
18
+ Parameters
19
+ ----------
20
+ data : any
21
+ The data to send to the OpenAI API
22
+
23
+ Returns
24
+ -------
25
+ any
26
+ The response from the OpenAI API
27
+ """
28
+ if isinstance(data, ChatCompletions):
29
+ response = data.choices[0].message
30
+ # tool calls available in response
31
+ if response.tool_calls:
32
+ return [
33
+ ToolCall(
34
+ id=tool_call.id,
35
+ name=tool_call.function.name,
36
+ arguments=tool_call.function.arguments,
37
+ )
38
+ for tool_call in response.tool_calls
39
+ ]
40
+ else:
41
+ return response.content
42
+
43
+ elif isinstance(data, EmbeddingsResult):
44
+ if len(data.data) == 0:
45
+ raise ValueError("Invalid data")
46
+ elif len(data.data) == 1:
47
+ return data.data[0].embedding
48
+ else:
49
+ return [item.embedding for item in data.data]
50
+ elif isinstance(data, Iterator):
51
+
52
+ def generator():
53
+ for chunk in data:
54
+ if (
55
+ len(chunk.choices) == 1
56
+ and chunk.choices[0].delta.content != None
57
+ ):
58
+ content = chunk.choices[0].delta.content
59
+ yield content
60
+
61
+ return PromptyStream("ServerlessProcessor", generator())
62
+ else:
63
+ return data
64
+
65
+ async def invoke_async(self, data: str) -> str:
66
+ """Invoke the Prompty Chat Parser (Async)
67
+
68
+ Parameters
69
+ ----------
70
+ data : str
71
+ The data to parse
72
+
73
+ Returns
74
+ -------
75
+ str
76
+ The parsed data
77
+ """
78
+ return self.invoke(data)