mirror of
https://github.com/langgenius/dify-plugin-sdks.git
synced 2026-07-22 02:15:22 -04:00
1ec2ff6d6c
* feat: add LLMStructuredOutput and LLMStructuredOutputInvocation for structured output handling - Introduced LLMStructuredOutput model class for structured output representation. - Added LLMStructuredOutputInvocation class to handle invocation with structured output. - Updated ModelInvocations to include LLMStructuredOutputInvocation. - Modified InvokeType enum to support LLMStructuredOutput type. * docs: update README.md to include support for LLM structured output in manifest versioning
116 lines
4.5 KiB
Python
116 lines
4.5 KiB
Python
from collections.abc import Generator
|
|
from typing import Any, Literal, cast, overload
|
|
|
|
from dify_plugin.core.entities.invocation import InvokeType
|
|
from dify_plugin.core.runtime import BackwardsInvocation
|
|
from dify_plugin.entities.model.llm import (
|
|
LLMModelConfig,
|
|
LLMResultChunkWithStructuredOutput,
|
|
LLMResultWithStructuredOutput,
|
|
LLMUsage,
|
|
)
|
|
from dify_plugin.entities.model.message import AssistantPromptMessage, PromptMessage, PromptMessageTool
|
|
|
|
|
|
class LLMStructuredOutputInvocation(BackwardsInvocation[LLMResultChunkWithStructuredOutput]):
|
|
@overload
|
|
def invoke(
|
|
self,
|
|
model_config: LLMModelConfig | dict,
|
|
prompt_messages: list[PromptMessage],
|
|
structured_output_schema: dict[str, Any],
|
|
tools: list[PromptMessageTool] | None = None,
|
|
stop: list[str] | None = None,
|
|
stream: Literal[True] = True,
|
|
) -> Generator[LLMResultChunkWithStructuredOutput, None, None]: ...
|
|
|
|
@overload
|
|
def invoke(
|
|
self,
|
|
model_config: LLMModelConfig | dict,
|
|
prompt_messages: list[PromptMessage],
|
|
structured_output_schema: dict[str, Any],
|
|
tools: list[PromptMessageTool] | None = None,
|
|
stop: list[str] | None = None,
|
|
stream: Literal[False] = False,
|
|
) -> LLMResultWithStructuredOutput: ...
|
|
|
|
@overload
|
|
def invoke(
|
|
self,
|
|
model_config: LLMModelConfig | dict,
|
|
prompt_messages: list[PromptMessage],
|
|
structured_output_schema: dict[str, Any],
|
|
tools: list[PromptMessageTool] | None = None,
|
|
stop: list[str] | None = None,
|
|
stream: bool = True,
|
|
) -> Generator[LLMResultChunkWithStructuredOutput, None, None] | LLMResultWithStructuredOutput: ...
|
|
|
|
def invoke(
|
|
self,
|
|
model_config: LLMModelConfig | dict,
|
|
prompt_messages: list[PromptMessage],
|
|
structured_output_schema: dict[str, Any],
|
|
tools: list[PromptMessageTool] | None = None,
|
|
stop: list[str] | None = None,
|
|
stream: bool = True,
|
|
) -> Generator[LLMResultChunkWithStructuredOutput, None, None] | LLMResultWithStructuredOutput:
|
|
"""
|
|
Invoke llm with structured output
|
|
"""
|
|
if isinstance(model_config, dict):
|
|
model_config = LLMModelConfig(**model_config)
|
|
|
|
data = {
|
|
**model_config.model_dump(),
|
|
"prompt_messages": [message.model_dump() for message in prompt_messages],
|
|
"structured_output_schema": structured_output_schema,
|
|
"tools": [tool.model_dump() for tool in tools] if tools else None,
|
|
"stop": stop,
|
|
"stream": stream,
|
|
}
|
|
|
|
if stream:
|
|
response = self._backwards_invoke(
|
|
InvokeType.LLMStructuredOutput,
|
|
LLMResultChunkWithStructuredOutput,
|
|
data,
|
|
)
|
|
response = cast(Generator[LLMResultChunkWithStructuredOutput, None, None], response)
|
|
return response
|
|
|
|
result = LLMResultWithStructuredOutput(
|
|
model=model_config.model,
|
|
message=AssistantPromptMessage(content=""),
|
|
usage=LLMUsage.empty_usage(),
|
|
structured_output=None,
|
|
)
|
|
|
|
assert isinstance(result.message.content, str)
|
|
|
|
for llm_result in self._backwards_invoke(
|
|
InvokeType.LLMStructuredOutput,
|
|
LLMResultChunkWithStructuredOutput,
|
|
data,
|
|
):
|
|
if isinstance(llm_result.delta.message.content, str):
|
|
result.message.content += llm_result.delta.message.content
|
|
if len(llm_result.delta.message.tool_calls) > 0:
|
|
result.message.tool_calls = llm_result.delta.message.tool_calls
|
|
if llm_result.delta.usage:
|
|
result.usage.prompt_tokens += llm_result.delta.usage.prompt_tokens
|
|
result.usage.completion_tokens += llm_result.delta.usage.completion_tokens
|
|
result.usage.total_tokens += llm_result.delta.usage.total_tokens
|
|
|
|
result.usage.completion_price = llm_result.delta.usage.completion_price
|
|
result.usage.prompt_price = llm_result.delta.usage.prompt_price
|
|
result.usage.total_price = llm_result.delta.usage.total_price
|
|
result.usage.currency = llm_result.delta.usage.currency
|
|
result.usage.latency = llm_result.delta.usage.latency
|
|
|
|
# Handle structured output
|
|
if llm_result.structured_output:
|
|
result.structured_output = llm_result.structured_output
|
|
|
|
return result
|