ci: script and workflow to update starter projects (#5195)
This commit is contained in:
parent
9ead14896a
commit
ba31d436c4
23 changed files with 1315 additions and 2077 deletions
22
.github/workflows/py_autofix.yml
vendored
22
.github/workflows/py_autofix.yml
vendored
|
|
@ -19,3 +19,25 @@ jobs:
|
|||
- uses: autofix-ci/action@ff86a557419858bb967097bfc916833f5647fa8c
|
||||
- name: Minimize uv cache
|
||||
run: uv cache prune --ci
|
||||
|
||||
update-starter-projects:
|
||||
name: Update Starter Projects
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: "Setup Environment"
|
||||
uses: ./.github/actions/setup-uv
|
||||
|
||||
- name: "Install dependencies"
|
||||
run: |
|
||||
uv sync --frozen
|
||||
uv pip install -e .
|
||||
|
||||
- name: Run starter projects update
|
||||
run: uv run python scripts/ci/update_starter_projects.py
|
||||
|
||||
- uses: autofix-ci/action@ff86a557419858bb967097bfc916833f5647fa8c
|
||||
|
||||
- name: Minimize uv cache
|
||||
run: uv cache prune --ci
|
||||
|
||||
|
|
|
|||
4
.github/workflows/style-check-py.yml
vendored
4
.github/workflows/style-check-py.yml
vendored
|
|
@ -6,10 +6,6 @@ on:
|
|||
paths:
|
||||
- "**/*.py"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
name: Ruff Style Check
|
||||
|
|
|
|||
43
scripts/ci/update_starter_projects.py
Normal file
43
scripts/ci/update_starter_projects.py
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
"""Script to update Langflow starter projects with the latest component versions."""
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
|
||||
import langflow.main # noqa: F401
|
||||
from langflow.initial_setup.setup import (
|
||||
get_project_data,
|
||||
load_starter_projects,
|
||||
update_edges_with_latest_component_versions,
|
||||
update_project_file,
|
||||
update_projects_components_with_latest_component_versions,
|
||||
)
|
||||
from langflow.interface.types import get_and_cache_all_types_dict
|
||||
from langflow.services.deps import get_settings_service
|
||||
from langflow.services.utils import initialize_services
|
||||
|
||||
|
||||
async def main():
|
||||
"""Updates the starter projects with the latest component versions.
|
||||
|
||||
Copies the code from langflow/initial_setup/setup.py. Doesn't use the
|
||||
create_or_update_starter_projects function directly to avoid sql interactions.
|
||||
"""
|
||||
await initialize_services(fix_migration=False)
|
||||
all_types_dict = await get_and_cache_all_types_dict(get_settings_service())
|
||||
|
||||
starter_projects = await load_starter_projects()
|
||||
for project_path, project in starter_projects:
|
||||
_, _, _, _, project_data, _, _, _, _ = get_project_data(project)
|
||||
do_update_starter_projects = os.environ.get("LANGFLOW_UPDATE_STARTER_PROJECTS", "true").lower() == "true"
|
||||
if do_update_starter_projects:
|
||||
updated_project_data = update_projects_components_with_latest_component_versions(
|
||||
project_data.copy(), all_types_dict
|
||||
)
|
||||
updated_project_data = update_edges_with_latest_component_versions(updated_project_data)
|
||||
if updated_project_data != project_data:
|
||||
project_data = updated_project_data
|
||||
await update_project_file(project_path, project, updated_project_data)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
|
|
@ -611,7 +611,13 @@ async def find_existing_flow(session, flow_id, flow_endpoint_name):
|
|||
return None
|
||||
|
||||
|
||||
async def create_or_update_starter_projects(all_types_dict: dict) -> None:
|
||||
async def create_or_update_starter_projects(all_types_dict: dict, *, do_create: bool = True) -> None:
|
||||
"""Create or update starter projects.
|
||||
|
||||
Args:
|
||||
all_types_dict (dict): Dictionary containing all component types and their templates
|
||||
do_create (bool, optional): Whether to create new projects. Defaults to True.
|
||||
"""
|
||||
async with async_session_scope() as session:
|
||||
new_folder = await create_starter_folder(session)
|
||||
starter_projects = await load_starter_projects()
|
||||
|
|
@ -639,7 +645,7 @@ async def create_or_update_starter_projects(all_types_dict: dict) -> None:
|
|||
project_data = updated_project_data
|
||||
# We also need to update the project data in the file
|
||||
await update_project_file(project_path, project, updated_project_data)
|
||||
if project_name and project_data:
|
||||
if do_create and project_name and project_data:
|
||||
for existing_project in await get_all_flows_similar_to_project(session, new_folder.id):
|
||||
await session.delete(existing_project)
|
||||
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -920,7 +920,7 @@
|
|||
"show": true,
|
||||
"title_case": false,
|
||||
"type": "code",
|
||||
"value": "from langflow.base.prompts.api_utils import process_prompt_template\nfrom langflow.custom import Component\nfrom langflow.inputs.inputs import DefaultPromptField\nfrom langflow.io import MessageTextInput, Output, PromptInput\nfrom langflow.schema.message import Message\nfrom langflow.template.utils import update_template_values\n\n\nclass PromptComponent(Component):\n display_name: str = \"Prompt\"\n description: str = \"Create a prompt template with dynamic variables.\"\n icon = \"prompts\"\n trace_type = \"prompt\"\n name = \"Prompt\"\n\n inputs = [\n PromptInput(name=\"template\", display_name=\"Template\"),\n MessageTextInput(\n name=\"tool_placeholder\",\n display_name=\"Tool Placeholder\",\n tool_mode=True,\n advanced=True,\n info=\"A placeholder input for tool mode.\",\n ),\n ]\n\n outputs = [\n Output(display_name=\"Prompt Message\", name=\"prompt\", method=\"build_prompt\"),\n ]\n\n async def build_prompt(self) -> Message:\n prompt = Message.from_template(**self._attributes)\n self.status = prompt.text\n return prompt\n\n def _update_template(self, frontend_node: dict):\n prompt_template = frontend_node[\"template\"][\"template\"][\"value\"]\n custom_fields = frontend_node[\"custom_fields\"]\n frontend_node_template = frontend_node[\"template\"]\n _ = process_prompt_template(\n template=prompt_template,\n name=\"template\",\n custom_fields=custom_fields,\n frontend_node_template=frontend_node_template,\n )\n return frontend_node\n\n def post_code_processing(self, new_frontend_node: dict, current_frontend_node: dict):\n \"\"\"This function is called after the code validation is done.\"\"\"\n frontend_node = super().post_code_processing(new_frontend_node, current_frontend_node)\n template = frontend_node[\"template\"][\"template\"][\"value\"]\n # Kept it duplicated for backwards compatibility\n _ = process_prompt_template(\n template=template,\n name=\"template\",\n custom_fields=frontend_node[\"custom_fields\"],\n frontend_node_template=frontend_node[\"template\"],\n )\n # Now that template is updated, we need to grab any values that were set in the current_frontend_node\n # and update the frontend_node with those values\n update_template_values(new_template=frontend_node, previous_template=current_frontend_node[\"template\"])\n return frontend_node\n\n def _get_fallback_input(self, **kwargs):\n return DefaultPromptField(**kwargs)\n"
|
||||
"value": "from langflow.base.prompts.api_utils import process_prompt_template\nfrom langflow.custom import Component\nfrom langflow.inputs.inputs import DefaultPromptField\nfrom langflow.io import MessageTextInput, Output, PromptInput\nfrom langflow.schema.message import Message\nfrom langflow.template.utils import update_template_values\n\n\nclass PromptComponent(Component):\n display_name: str = \"Prompt\"\n description: str = \"Create a prompt template with dynamic variables.\"\n icon = \"prompts\"\n trace_type = \"prompt\"\n name = \"Prompt\"\n\n inputs = [\n PromptInput(name=\"template\", display_name=\"Template\"),\n MessageTextInput(\n name=\"tool_placeholder\",\n display_name=\"Tool Placeholder\",\n tool_mode=True,\n advanced=True,\n info=\"A placeholder input for tool mode.\",\n ),\n ]\n\n outputs = [\n Output(display_name=\"Prompt Message\", name=\"prompt\", method=\"build_prompt\"),\n ]\n\n async def build_prompt(self) -> Message:\n prompt = Message.from_template(**self._attributes)\n self.status = prompt.text\n return prompt\n\n def _update_template(self, frontend_node: dict):\n prompt_template = frontend_node[\"template\"][\"template\"][\"value\"]\n custom_fields = frontend_node[\"custom_fields\"]\n frontend_node_template = frontend_node[\"template\"]\n _ = process_prompt_template(\n template=prompt_template,\n name=\"template\",\n custom_fields=custom_fields,\n frontend_node_template=frontend_node_template,\n )\n return frontend_node\n\n async def post_code_processing(self, new_frontend_node: dict, current_frontend_node: dict):\n \"\"\"This function is called after the code validation is done.\"\"\"\n frontend_node = await super().post_code_processing(new_frontend_node, current_frontend_node)\n template = frontend_node[\"template\"][\"template\"][\"value\"]\n # Kept it duplicated for backwards compatibility\n _ = process_prompt_template(\n template=template,\n name=\"template\",\n custom_fields=frontend_node[\"custom_fields\"],\n frontend_node_template=frontend_node[\"template\"],\n )\n # Now that template is updated, we need to grab any values that were set in the current_frontend_node\n # and update the frontend_node with those values\n update_template_values(new_template=frontend_node, previous_template=current_frontend_node[\"template\"])\n return frontend_node\n\n def _get_fallback_input(self, **kwargs):\n return DefaultPromptField(**kwargs)\n"
|
||||
},
|
||||
"template": {
|
||||
"_input_type": "PromptInput",
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -269,9 +269,11 @@ class ArizePhoenixTracer(BaseTracer):
|
|||
if not self._ready:
|
||||
return
|
||||
|
||||
def _convert_to_arize_phoenix_types(self, io_dict: dict[str, Any]):
|
||||
def _convert_to_arize_phoenix_types(self, io_dict: dict[str | Any, Any]) -> dict[str, Any]:
|
||||
"""Converts data types to Arize/Phoenix compatible formats."""
|
||||
return {key: self._convert_to_arize_phoenix_type(value) for key, value in io_dict.items()}
|
||||
return {
|
||||
str(key): self._convert_to_arize_phoenix_type(value) for key, value in io_dict.items() if key is not None
|
||||
}
|
||||
|
||||
def _convert_to_arize_phoenix_type(self, value):
|
||||
"""Recursively converts a value to a Arize/Phoenix compatible type."""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue