diff --git a/README.md b/README.md index 419addb..a1eb063 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,9 @@ source .venv/bin/activate We have provided a custom run.yaml file to specify the required providers. Use the following command to run the Llama Stack with the custom configuration file. ``` +cp pyproject.llama-stack.toml pyproject.toml +uv sync +source .venv/bin/activate uv run llama stack run run.yaml ``` @@ -117,6 +120,9 @@ uv run llama-stack-client configure --endpoint http://localhost:8321 --api-key n ## Run the application Code ```bash +cp pyproject.orig.toml pyproject.toml +uv sync +source .venv/bin/activate uv run streamlit run streamlit_app.py ``` diff --git a/pyproject.orig.toml b/pyproject.orig.toml new file mode 100644 index 0000000..556bdb1 --- /dev/null +++ b/pyproject.orig.toml @@ -0,0 +1,38 @@ +[project] +name = "llama-stack-agentic-sample" +version = "0.1.0" +description = "Llama-Stack LangGraph Customer Service Example" +readme = "README.md" +requires-python = ">=3.12" +dependencies = [ + "docling>=2.63.0", + "llama-stack-client>=0.3.1", + "llama-stack>=0.3.1", + "pygithub>=2.8.1", + "pyyaml>=6.0.3", + "langgraph>=1.0.4", + "ollama>=0.6.1", + "mcp>=1.23.1", + "chardet>=5.2.0", + "streamlit>=1.52.1", + "grandalf>=0.8", +] + +[tool.setuptools.packages.find] +where = ["src"] + +[dependency-groups] +dev = ["ruff>=0.8.0", "pytest>=7.4.0", "pre-commit>=3.5.0"] + +[tool.ruff] +line-length = 88 +target-version = "py312" +exclude = ["tests", "*.pyi"] +include = ["src/**/*.py", "streamlit_app.py"] + +[tool.ruff.lint] +select = ["E", "F", "I"] +ignore = [] + +[tool.ruff.lint.isort] +known-first-party = ["src"] diff --git a/src/ingest.py b/src/ingest.py index 0d56278..32c8aba 100644 --- a/src/ingest.py +++ b/src/ingest.py @@ -5,7 +5,7 @@ import tempfile import time from pathlib import Path -from typing import Any +from typing import Any, cast import requests import yaml @@ -293,7 +293,7 @@ def _fetch_github_dir_contents( if isinstance(c, ContentFile): contents_list.append(c) elif hasattr(c, "type") and hasattr(c, "name"): - contents_list.append(c) # type: ignore[arg-type] + contents_list.append(cast(ContentFile, c)) pdf_files.extend( self._fetch_github_dir_contents( repo, contents_list, branch, path, download_dir @@ -384,7 +384,7 @@ def fetch_from_github( if isinstance(c, ContentFile): contents_list.append(c) elif hasattr(c, "type") and hasattr(c, "name"): - contents_list.append(c) # type: ignore[arg-type] + contents_list.append(cast(ContentFile, c)) pdf_files = self._fetch_github_dir_contents( repo, contents_list, branch, path, download_dir ) diff --git a/src/methods.py b/src/methods.py index 36186a7..fa91eeb 100644 --- a/src/methods.py +++ b/src/methods.py @@ -300,7 +300,7 @@ def git_agent( if not tools_llm: raise AgentRunMethodParameterError("tools_llm is required in git agent") - openai_mcp_tool: "dict[str, Any]" = { + openai_mcp_tool: "Any" = { "type": "mcp", "server_label": "github", "server_url": "https://api.githubcopilot.com/mcp/", @@ -319,7 +319,7 @@ def git_agent( sub_id=state["submission_id"], user_question=state["input"], ), - tools=[openai_mcp_tool], # type: ignore[arg-type] + tools=[openai_mcp_tool], ) logger.debug("git_agent response returned") @@ -371,7 +371,7 @@ def git_agent( issue_id=gh_issue, comment_body=body_as_string, ), - tools=[openai_mcp_tool], # type: ignore[arg-type] + tools=[openai_mcp_tool], timeout=240.0, # the bigger comment calls can take # especially long ... put a cap on it ) @@ -440,7 +440,7 @@ def pod_agent( if not tools_llm: raise AgentRunMethodParameterError("tools_llm is required in git agent") - openai_mcp_tool: "dict[str, Any]" = { + openai_mcp_tool: "Any" = { "type": "mcp", "server_label": "OpenShift / Kubernetes MCP Tools", "server_url": MCP_SERVER_URL, @@ -455,7 +455,7 @@ def pod_agent( resp = openai_client.responses.create( model=tools_llm, input=WorkflowAgentPrompts.POD_PROMPT.format(namespace=state["namespace"]), - tools=[openai_mcp_tool], # type: ignore[arg-type] + tools=[openai_mcp_tool], ) logger.debug( f"K8S Agent successful return MCP request " @@ -518,7 +518,7 @@ def perf_agent( if not tools_llm: raise AgentRunMethodParameterError("tools_llm is required in git agent") - openai_mcp_tool: "dict[str, Any]" = { + openai_mcp_tool: "Any" = { "type": "mcp", "server_label": "OpenShift / Kubernetes MCP Tools", "server_url": MCP_SERVER_URL, @@ -534,7 +534,7 @@ def perf_agent( resp = openai_client.responses.create( model=tools_llm, input=WorkflowAgentPrompts.PERF_PROMPT.format(namespace=state["namespace"]), - tools=[openai_mcp_tool], # type: ignore[arg-type] + tools=[openai_mcp_tool], ) logger.debug( f"K8S perf Agent successful return MCP request " diff --git a/src/workflow.py b/src/workflow.py index 27df3c1..e028bab 100644 --- a/src/workflow.py +++ b/src/workflow.py @@ -72,7 +72,7 @@ def _call_openai_llm(self, state: "WorkflowState") -> "str": messages = self._convert_messages_to_openai_format(state) completion = self.rag_service.openai_client.chat.completions.create( model=INFERENCE_MODEL, - messages=messages, # type: ignore[invalid-argument-type] + messages=cast("Any", messages), ) return completion.choices[0].message.content or "" @@ -206,7 +206,7 @@ def llm_node(state: "WorkflowState") -> "WorkflowState": rag_response = client_to_use.responses.create( model=INFERENCE_MODEL, input=rag_prompt, - tools=[file_search_tool], # type: ignore[invalid-argument-type] + tools=cast("Any", [file_search_tool]), ) rag_end_time = time.time() state["rag_query_time"] = rag_end_time - rag_start_time @@ -290,7 +290,7 @@ def llm_node(state: "WorkflowState") -> "WorkflowState": return state - agent_builder = StateGraph(WorkflowState) # type: ignore[arg-type] + agent_builder = StateGraph(cast("Any", WorkflowState)) agent_builder.add_node(f"{department_name}_set_message", init_message) agent_builder.add_node("llm_node", llm_node) agent_builder.add_edge(START, f"{department_name}_set_message") @@ -450,7 +450,7 @@ def perf_agent_node(state: "WorkflowState") -> "WorkflowState": tools_llm=tools_llm, ) - overall_workflow = StateGraph(WorkflowState) # type: ignore[arg-type] + overall_workflow = StateGraph(cast("Any", WorkflowState)) overall_workflow.add_node( "classification_agent", classification_node, diff --git a/streamlit_app.py b/streamlit_app.py index f441169..97e34a8 100644 --- a/streamlit_app.py +++ b/streamlit_app.py @@ -586,7 +586,7 @@ def _run_async_in_thread(coro): async def run_workflow_task_async( - workflow: "Workflow", question: "str", submission_id: "str" + workflow: "Any", question: "str", submission_id: "str" ) -> "None": """ async task to run a single workflow with concurrent operations @@ -599,7 +599,7 @@ async def run_workflow_task_async( # the question through appropriate agents (classification -> dept agents) # Note: workflow.invoke is synchronous but we're in an async context # to allow future async operations within the workflow - result = workflow.invoke( # type: ignore[attr-defined] + result = workflow.invoke( { "input": question, "submission_id": submission_id,