Skip to content

Commit e7c85ce

Browse files
elena-kolevskaajstewartmarcduiker
authored
Cherrypicks 1.15 commits back to main (#789)
* Catch error in sdk when workflow instance not found (#771) * Catch error in sdk when workflow instance not found Signed-off-by: Elena Kolevska <[email protected]> * fixes demo workflow example test Signed-off-by: Elena Kolevska <[email protected]> * Only return None for the correct error Signed-off-by: Elena Kolevska <[email protected]> * Adds test Signed-off-by: Elena Kolevska <[email protected]> * Linter Signed-off-by: Elena Kolevska <[email protected]> * Extends test Signed-off-by: Elena Kolevska <[email protected]> --------- Signed-off-by: Elena Kolevska <[email protected]> * Fix get_worfklow_state docstring to match fetch_payloads default (#772) Signed-off-by: Adam Stewart <[email protected]> Co-authored-by: Elena Kolevska <[email protected]> Signed-off-by: Elena Kolevska <[email protected]> * Remove test sleep (#778) Signed-off-by: Elena Kolevska <[email protected]> * Restores sleeps in test, as it was decided not to invest making synchronous the APIs that are getting deleted next version (#781) Signed-off-by: Elena Kolevska <[email protected]> * Updates workflows docs to use the new workflows client (#780) * Updates docs Signed-off-by: Elena Kolevska <[email protected]> * More workflows docs Signed-off-by: Elena Kolevska <[email protected]> * Move workflows examples, based on review Signed-off-by: Elena Kolevska <[email protected]> * Small fixes Signed-off-by: Elena Kolevska <[email protected]> --------- Signed-off-by: Elena Kolevska <[email protected]> * Workflow fixes and improvements (#784) * Converts demo_workflow example to DaprWorkflowClient and removes default timeout of 60seconds on `wait_for_workflow_start` and `wait_for_workflow_completion` Signed-off-by: Elena Kolevska <[email protected]> * Bumps durable task library. Signed-off-by: Elena Kolevska <[email protected]> --------- Signed-off-by: Elena Kolevska <[email protected]> # Conflicts: # ext/dapr-ext-workflow/setup.cfg * Retry streaming subscription on status UNKNOWN as well (#783) Signed-off-by: Elena Kolevska <[email protected]> * Adds examples and docs for cloud events messages (#785) Signed-off-by: Elena Kolevska <[email protected]> * Conversation API support (#787) * Conversation API support (sync) Signed-off-by: Elena Kolevska <[email protected]> * async conversation api support Signed-off-by: Elena Kolevska <[email protected]> * Adds docs Signed-off-by: Elena Kolevska <[email protected]> * Ignore validation of x.com link that needs authentication Signed-off-by: Elena Kolevska <[email protected]> * Registers e2e test. Clean up. Signed-off-by: Elena Kolevska <[email protected]> * Apply suggestions from code review Co-authored-by: Marc Duiker <[email protected]> Signed-off-by: Elena Kolevska <[email protected]> * Linter Signed-off-by: Elena Kolevska <[email protected]> * Updates protos and renames parameter Signed-off-by: Elena Kolevska <[email protected]> * Improves error handling Signed-off-by: Elena Kolevska <[email protected]> --------- Signed-off-by: Elena Kolevska <[email protected]> Signed-off-by: Elena Kolevska <[email protected]> Co-authored-by: Marc Duiker <[email protected]> Signed-off-by: Elena Kolevska <[email protected]> * Updates dev version to 1.15.0 Signed-off-by: Elena Kolevska <[email protected]> --------- Signed-off-by: Elena Kolevska <[email protected]> Signed-off-by: Adam Stewart <[email protected]> Signed-off-by: Elena Kolevska <[email protected]> Co-authored-by: Adam Stewart <[email protected]> Co-authored-by: Marc Duiker <[email protected]>
1 parent fc4980d commit e7c85ce

File tree

46 files changed

+1537
-689
lines changed

Some content is hidden

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

46 files changed

+1537
-689
lines changed

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
[![GitHub issue custom search in repo](https://img.shields.io/github/issues-search/dapr/python-sdk?query=type%3Aissue%20is%3Aopen%20label%3A%22good%20first%20issue%22&label=Good%20first%20issues&style=flat&logo=github)](https://github.com/dapr/python-sdk/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22)
99
[![Discord](https://img.shields.io/discord/778680217417809931?label=Discord&style=flat&logo=discord)](http://bit.ly/dapr-discord)
1010
[![YouTube Channel Views](https://img.shields.io/youtube/channel/views/UCtpSQ9BLB_3EXdWAUQYwnRA?style=flat&label=YouTube%20views&logo=youtube)](https://youtube.com/@daprdev)
11+
<!-- IGNORE_LINKS -->
1112
[![X (formerly Twitter) Follow](https://img.shields.io/twitter/follow/daprdev?logo=x&style=flat)](https://twitter.com/daprdev)
13+
<!-- END_IGNORE -->
1214

1315
[Dapr](https://docs.dapr.io/concepts/overview/) is a portable, event-driven, serverless runtime for building distributed applications across cloud and edge.
1416

dapr/aio/clients/grpc/client.py

+60
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
from google.protobuf.message import Message as GrpcMessage
3131
from google.protobuf.empty_pb2 import Empty as GrpcEmpty
32+
from google.protobuf.any_pb2 import Any as GrpcAny
3233

3334
import grpc.aio # type: ignore
3435
from grpc.aio import ( # type: ignore
@@ -75,9 +76,12 @@
7576
InvokeMethodRequest,
7677
BindingRequest,
7778
TransactionalStateOperation,
79+
ConversationInput,
7880
)
7981
from dapr.clients.grpc._response import (
8082
BindingResponse,
83+
ConversationResponse,
84+
ConversationResult,
8185
DaprResponse,
8286
GetSecretResponse,
8387
GetBulkSecretResponse,
@@ -1711,6 +1715,62 @@ async def purge_workflow(self, instance_id: str, workflow_component: str) -> Dap
17111715
except grpc.aio.AioRpcError as err:
17121716
raise DaprInternalError(err.details())
17131717

1718+
async def converse_alpha1(
1719+
self,
1720+
name: str,
1721+
inputs: List[ConversationInput],
1722+
*,
1723+
context_id: Optional[str] = None,
1724+
parameters: Optional[Dict[str, GrpcAny]] = None,
1725+
metadata: Optional[Dict[str, str]] = None,
1726+
scrub_pii: Optional[bool] = None,
1727+
temperature: Optional[float] = None,
1728+
) -> ConversationResponse:
1729+
"""Invoke an LLM using the conversation API (Alpha).
1730+
1731+
Args:
1732+
name: Name of the LLM component to invoke
1733+
inputs: List of conversation inputs
1734+
context_id: Optional ID for continuing an existing chat
1735+
parameters: Optional custom parameters for the request
1736+
metadata: Optional metadata for the component
1737+
scrub_pii: Optional flag to scrub PII from inputs and outputs
1738+
temperature: Optional temperature setting for the LLM to optimize for creativity or predictability
1739+
1740+
Returns:
1741+
ConversationResponse containing the conversation results
1742+
1743+
Raises:
1744+
DaprGrpcError: If the Dapr runtime returns an error
1745+
"""
1746+
inputs_pb = [
1747+
api_v1.ConversationInput(content=inp.content, role=inp.role, scrubPII=inp.scrub_pii)
1748+
for inp in inputs
1749+
]
1750+
1751+
request = api_v1.ConversationRequest(
1752+
name=name,
1753+
inputs=inputs_pb,
1754+
contextID=context_id,
1755+
parameters=parameters or {},
1756+
metadata=metadata or {},
1757+
scrubPII=scrub_pii,
1758+
temperature=temperature,
1759+
)
1760+
1761+
try:
1762+
response = await self._stub.ConverseAlpha1(request)
1763+
1764+
outputs = [
1765+
ConversationResult(result=output.result, parameters=output.parameters)
1766+
for output in response.outputs
1767+
]
1768+
1769+
return ConversationResponse(context_id=response.contextID, outputs=outputs)
1770+
1771+
except grpc.aio.AioRpcError as err:
1772+
raise DaprGrpcError(err) from err
1773+
17141774
async def wait(self, timeout_s: float):
17151775
"""Waits for sidecar to be available within the timeout.
17161776

dapr/clients/grpc/_request.py

+10
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
import io
1717
from enum import Enum
18+
from dataclasses import dataclass
1819
from typing import Dict, Optional, Union
1920

2021
from google.protobuf.any_pb2 import Any as GrpcAny
@@ -418,3 +419,12 @@ def __next__(self):
418419

419420
self.seq += 1
420421
return request_proto
422+
423+
424+
@dataclass
425+
class ConversationInput:
426+
"""A single input message for the conversation."""
427+
428+
content: str
429+
role: Optional[str] = None
430+
scrub_pii: Optional[bool] = None

dapr/clients/grpc/_response.py

+17
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import contextlib
1919
import json
2020
import threading
21+
from dataclasses import dataclass, field
2122
from datetime import datetime
2223
from enum import Enum
2324
from typing import (
@@ -1070,3 +1071,19 @@ class EncryptResponse(CryptoResponse[TCryptoResponse]):
10701071

10711072
class DecryptResponse(CryptoResponse[TCryptoResponse]):
10721073
...
1074+
1075+
1076+
@dataclass
1077+
class ConversationResult:
1078+
"""Result from a single conversation input."""
1079+
1080+
result: str
1081+
parameters: Dict[str, GrpcAny] = field(default_factory=dict)
1082+
1083+
1084+
@dataclass
1085+
class ConversationResponse:
1086+
"""Response from the conversation API."""
1087+
1088+
context_id: Optional[str]
1089+
outputs: List[ConversationResult]

dapr/clients/grpc/client.py

+60
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
from datetime import datetime
2828
from google.protobuf.message import Message as GrpcMessage
2929
from google.protobuf.empty_pb2 import Empty as GrpcEmpty
30+
from google.protobuf.any_pb2 import Any as GrpcAny
3031

3132
import grpc # type: ignore
3233
from grpc import ( # type: ignore
@@ -64,6 +65,7 @@
6465
TransactionalStateOperation,
6566
EncryptRequestIterator,
6667
DecryptRequestIterator,
68+
ConversationInput,
6769
)
6870
from dapr.clients.grpc._response import (
6971
BindingResponse,
@@ -88,6 +90,8 @@
8890
EncryptResponse,
8991
DecryptResponse,
9092
TopicEventResponse,
93+
ConversationResponse,
94+
ConversationResult,
9195
)
9296

9397

@@ -1713,6 +1717,62 @@ def purge_workflow(self, instance_id: str, workflow_component: str) -> DaprRespo
17131717
except RpcError as err:
17141718
raise DaprInternalError(err.details())
17151719

1720+
def converse_alpha1(
1721+
self,
1722+
name: str,
1723+
inputs: List[ConversationInput],
1724+
*,
1725+
context_id: Optional[str] = None,
1726+
parameters: Optional[Dict[str, GrpcAny]] = None,
1727+
metadata: Optional[Dict[str, str]] = None,
1728+
scrub_pii: Optional[bool] = None,
1729+
temperature: Optional[float] = None,
1730+
) -> ConversationResponse:
1731+
"""Invoke an LLM using the conversation API (Alpha).
1732+
1733+
Args:
1734+
name: Name of the LLM component to invoke
1735+
inputs: List of conversation inputs
1736+
context_id: Optional ID for continuing an existing chat
1737+
parameters: Optional custom parameters for the request
1738+
metadata: Optional metadata for the component
1739+
scrub_pii: Optional flag to scrub PII from inputs and outputs
1740+
temperature: Optional temperature setting for the LLM to optimize for creativity or predictability
1741+
1742+
Returns:
1743+
ConversationResponse containing the conversation results
1744+
1745+
Raises:
1746+
DaprGrpcError: If the Dapr runtime returns an error
1747+
"""
1748+
1749+
inputs_pb = [
1750+
api_v1.ConversationInput(content=inp.content, role=inp.role, scrubPII=inp.scrub_pii)
1751+
for inp in inputs
1752+
]
1753+
1754+
request = api_v1.ConversationRequest(
1755+
name=name,
1756+
inputs=inputs_pb,
1757+
contextID=context_id,
1758+
parameters=parameters or {},
1759+
metadata=metadata or {},
1760+
scrubPII=scrub_pii,
1761+
temperature=temperature,
1762+
)
1763+
1764+
try:
1765+
response, call = self.retry_policy.run_rpc(self._stub.ConverseAlpha1.with_call, request)
1766+
1767+
outputs = [
1768+
ConversationResult(result=output.result, parameters=output.parameters)
1769+
for output in response.outputs
1770+
]
1771+
1772+
return ConversationResponse(context_id=response.contextID, outputs=outputs)
1773+
except RpcError as err:
1774+
raise DaprGrpcError(err) from err
1775+
17161776
def wait(self, timeout_s: float):
17171777
"""Waits for sidecar to be available within the timeout.
17181778

dapr/clients/grpc/subscription.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ def next_message(self):
8484
return SubscriptionMessage(message.event_message)
8585
except RpcError as e:
8686
# If Dapr can't be reached, wait until it's ready and reconnect the stream
87-
if e.code() == StatusCode.UNAVAILABLE:
87+
if e.code() == StatusCode.UNAVAILABLE or e.code() == StatusCode.UNKNOWN:
8888
print(
8989
f'gRPC error while reading from stream: {e.details()}, Status Code: {e.code()}'
9090
)

0 commit comments

Comments
 (0)