Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

run_workflow.py 6.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. #!/usr/bin/env python3
  2. import sys
  3. from pathlib import Path
  4. sys.path.append(str(Path(__file__).parent.parent))
  5. import httpx
  6. import json
  7. from common import config_helper, Logger
  8. def run_workflow(question: str = "fake question", streaming: bool = True) -> None:
  9. """Run the workflow app with a question."""
  10. log = Logger("RunWorkflow")
  11. log.header("Running Workflow")
  12. # Read API key from config
  13. api_token = config_helper.get_api_key()
  14. if not api_token:
  15. log.error("No API token found in config")
  16. log.info("Please run create_api_key.py first to create an API key")
  17. return
  18. log.key_value("Question", question)
  19. log.key_value("Mode", "Streaming" if streaming else "Blocking")
  20. log.separator()
  21. # API endpoint for running workflow
  22. base_url = "http://localhost:5001"
  23. run_endpoint = f"{base_url}/v1/workflows/run"
  24. # Run payload
  25. run_payload = {
  26. "inputs": {"question": question},
  27. "user": "default user",
  28. "response_mode": "streaming" if streaming else "blocking",
  29. }
  30. headers = {
  31. "Authorization": f"Bearer {api_token}",
  32. "Content-Type": "application/json",
  33. }
  34. try:
  35. # Make the run request
  36. with httpx.Client(timeout=30.0) as client:
  37. if streaming:
  38. # Handle streaming response
  39. with client.stream(
  40. "POST",
  41. run_endpoint,
  42. json=run_payload,
  43. headers=headers,
  44. ) as response:
  45. if response.status_code == 200:
  46. log.success("Workflow started successfully!")
  47. log.separator()
  48. log.step("Streaming response:")
  49. for line in response.iter_lines():
  50. if line.startswith("data: "):
  51. data_str = line[6:] # Remove "data: " prefix
  52. if data_str == "[DONE]":
  53. log.success("Workflow completed!")
  54. break
  55. try:
  56. data = json.loads(data_str)
  57. event = data.get("event")
  58. if event == "workflow_started":
  59. log.progress(
  60. f"Workflow started: {data.get('data', {}).get('id')}"
  61. )
  62. elif event == "node_started":
  63. node_data = data.get("data", {})
  64. log.progress(
  65. f"Node started: {node_data.get('node_type')} - {node_data.get('title')}"
  66. )
  67. elif event == "node_finished":
  68. node_data = data.get("data", {})
  69. log.progress(
  70. f"Node finished: {node_data.get('node_type')} - {node_data.get('title')}"
  71. )
  72. # Print output if it's the LLM node
  73. outputs = node_data.get("outputs", {})
  74. if outputs.get("text"):
  75. log.separator()
  76. log.info("💬 LLM Response:")
  77. log.info(outputs.get("text"), indent=2)
  78. log.separator()
  79. elif event == "workflow_finished":
  80. workflow_data = data.get("data", {})
  81. outputs = workflow_data.get("outputs", {})
  82. if outputs.get("answer"):
  83. log.separator()
  84. log.info("📤 Final Answer:")
  85. log.info(outputs.get("answer"), indent=2)
  86. log.separator()
  87. log.key_value(
  88. "Total tokens",
  89. str(workflow_data.get("total_tokens", 0)),
  90. )
  91. log.key_value(
  92. "Total steps",
  93. str(workflow_data.get("total_steps", 0)),
  94. )
  95. elif event == "error":
  96. log.error(f"Error: {data.get('message')}")
  97. except json.JSONDecodeError:
  98. # Some lines might not be JSON
  99. pass
  100. else:
  101. log.error(
  102. f"Workflow run failed with status code: {response.status_code}"
  103. )
  104. log.debug(f"Response: {response.text}")
  105. else:
  106. # Handle blocking response
  107. response = client.post(
  108. run_endpoint,
  109. json=run_payload,
  110. headers=headers,
  111. )
  112. if response.status_code == 200:
  113. log.success("Workflow completed successfully!")
  114. response_data = response.json()
  115. log.separator()
  116. log.debug(f"Full response: {json.dumps(response_data, indent=2)}")
  117. # Extract the answer if available
  118. outputs = response_data.get("data", {}).get("outputs", {})
  119. if outputs.get("answer"):
  120. log.separator()
  121. log.info("📤 Final Answer:")
  122. log.info(outputs.get("answer"), indent=2)
  123. else:
  124. log.error(
  125. f"Workflow run failed with status code: {response.status_code}"
  126. )
  127. log.debug(f"Response: {response.text}")
  128. except httpx.ConnectError:
  129. log.error("Could not connect to Dify API at http://localhost:5001")
  130. log.info("Make sure the API server is running with: ./dev/start-api")
  131. except httpx.TimeoutException:
  132. log.error("Request timed out")
  133. except Exception as e:
  134. log.error(f"An error occurred: {e}")
  135. if __name__ == "__main__":
  136. # Allow passing question as command line argument
  137. if len(sys.argv) > 1:
  138. question = " ".join(sys.argv[1:])
  139. else:
  140. question = "What is the capital of France?"
  141. run_workflow(question=question, streaming=True)