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

Sign up to get free protection for your applications and to get access to all the features.
@@ -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)