workflow run block description generation (#1482)

This commit is contained in:
Shuchang Zheng 2025-01-03 15:55:57 -08:00 committed by GitHub
parent 60e051eeb5
commit 187c18d83c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 91 additions and 2 deletions

View file

@ -0,0 +1,31 @@
"""add description to workflow run block
Revision ID: 32e2f138f7fd
Revises: 521241e64aed
Create Date: 2025-01-03 23:49:40.290858+00:00
"""
from typing import Sequence, Union
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision: str = "32e2f138f7fd"
down_revision: Union[str, None] = "521241e64aed"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column("workflow_run_blocks", sa.Column("description", sa.String(), nullable=True))
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column("workflow_run_blocks", "description")
# ### end Alembic commands ###

View file

@ -0,0 +1,10 @@
We are building workflow automations. There are many blocks in a workflow. Generate a summary for the following block to help the user understand what the block is planning to do.
{{ block }}
Respond with the following JSON format:
```
{
"summary": str // Be concise and to the point. Summarize the block in one sentence with no more than 20 words. Use languages like "Will do something", "Planning to do something", "Going to do something" and replace the "do something" with the actual action the block is planning to do.
}
```

View file

@ -2146,11 +2146,11 @@ class AgentDB:
async def update_workflow_run_block( async def update_workflow_run_block(
self, self,
workflow_run_block_id: str, workflow_run_block_id: str,
organization_id: str | None = None,
status: BlockStatus | None = None, status: BlockStatus | None = None,
output: dict | list | str | None = None, output: dict | list | str | None = None,
failure_reason: str | None = None, failure_reason: str | None = None,
task_id: str | None = None, task_id: str | None = None,
organization_id: str | None = None,
loop_values: list | None = None, loop_values: list | None = None,
current_value: str | None = None, current_value: str | None = None,
current_index: int | None = None, current_index: int | None = None,
@ -2160,6 +2160,7 @@ class AgentDB:
body: str | None = None, body: str | None = None,
prompt: str | None = None, prompt: str | None = None,
wait_sec: int | None = None, wait_sec: int | None = None,
description: str | None = None,
) -> WorkflowRunBlock: ) -> WorkflowRunBlock:
async with self.Session() as session: async with self.Session() as session:
workflow_run_block = ( workflow_run_block = (
@ -2196,6 +2197,8 @@ class AgentDB:
workflow_run_block.prompt = prompt workflow_run_block.prompt = prompt
if wait_sec: if wait_sec:
workflow_run_block.wait_sec = wait_sec workflow_run_block.wait_sec = wait_sec
if description:
workflow_run_block.description = description
await session.commit() await session.commit()
await session.refresh(workflow_run_block) await session.refresh(workflow_run_block)
else: else:

View file

@ -494,6 +494,7 @@ class WorkflowRunBlockModel(Base):
String, ForeignKey("workflow_run_blocks.workflow_run_block_id"), nullable=True String, ForeignKey("workflow_run_blocks.workflow_run_block_id"), nullable=True
) )
organization_id = Column(String, ForeignKey("organizations.organization_id"), nullable=True) organization_id = Column(String, ForeignKey("organizations.organization_id"), nullable=True)
description = Column(String, nullable=True)
task_id = Column(String, ForeignKey("tasks.task_id"), nullable=True) task_id = Column(String, ForeignKey("tasks.task_id"), nullable=True)
label = Column(String, nullable=True) label = Column(String, nullable=True)
block_type = Column(String, nullable=False) block_type = Column(String, nullable=False)

View file

@ -382,6 +382,7 @@ def convert_to_workflow_run_block(
workflow_run_id=workflow_run_block_model.workflow_run_id, workflow_run_id=workflow_run_block_model.workflow_run_id,
organization_id=workflow_run_block_model.organization_id, organization_id=workflow_run_block_model.organization_id,
parent_workflow_run_block_id=workflow_run_block_model.parent_workflow_run_block_id, parent_workflow_run_block_id=workflow_run_block_model.parent_workflow_run_block_id,
description=workflow_run_block_model.description,
block_type=BlockType(workflow_run_block_model.block_type), block_type=BlockType(workflow_run_block_model.block_type),
label=workflow_run_block_model.label, label=workflow_run_block_model.label,
status=BlockStatus(workflow_run_block_model.status), status=BlockStatus(workflow_run_block_model.status),

View file

@ -15,6 +15,7 @@ class WorkflowRunBlock(BaseModel):
workflow_run_block_id: str workflow_run_block_id: str
workflow_run_id: str workflow_run_id: str
organization_id: str | None = None organization_id: str | None = None
description: str | None = None
parent_workflow_run_block_id: str | None = None parent_workflow_run_block_id: str | None = None
block_type: BlockType block_type: BlockType
label: str | None = None label: str | None = None

View file

@ -208,6 +208,49 @@ class Block(BaseModel, abc.ABC):
block_type=self.block_type, block_type=self.block_type,
continue_on_failure=self.continue_on_failure, continue_on_failure=self.continue_on_failure,
) )
workflow_run_block_id = workflow_run_block.workflow_run_block_id
description = None
try:
block_data = self.model_dump(
exclude={
"workflow_run_block_id",
"organization_id",
"task_id",
"workflow_run_id",
"parent_workflow_run_block_id",
"label",
"status",
"output",
"continue_on_failure",
"failure_reason",
"actions",
"created_at",
"modified_at",
},
exclude_none=True,
)
description_generation_prompt = prompt_engine.load_prompt(
"generate_workflow_run_block_description",
block=block_data,
)
json_response = await app.SECONDARY_LLM_API_HANDLER(prompt=description_generation_prompt)
description = json_response.get("summary")
LOG.info(
"Generated description for the workflow run block",
description=description,
workflow_run_block_id=workflow_run_block.workflow_run_block_id,
)
except Exception as e:
LOG.exception("Failed to generate description for the workflow run block", error=e)
if description:
workflow_run_block = await app.DATABASE.update_workflow_run_block(
workflow_run_block_id=workflow_run_block.workflow_run_block_id,
description=description,
organization_id=organization_id,
)
# create a screenshot # create a screenshot
browser_state = app.BROWSER_MANAGER.get_for_workflow_run(workflow_run_id) browser_state = app.BROWSER_MANAGER.get_for_workflow_run(workflow_run_id)
if not browser_state: if not browser_state:
@ -220,7 +263,6 @@ class Block(BaseModel, abc.ABC):
artifact_type=ArtifactType.SCREENSHOT_LLM, artifact_type=ArtifactType.SCREENSHOT_LLM,
data=screenshot, data=screenshot,
) )
workflow_run_block_id = workflow_run_block.workflow_run_block_id
return await self.execute(workflow_run_id, workflow_run_block_id, organization_id=organization_id, **kwargs) return await self.execute(workflow_run_id, workflow_run_block_id, organization_id=organization_id, **kwargs)
except Exception as e: except Exception as e:
LOG.exception( LOG.exception(