Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. #!/usr/bin/env python3
  2. import sys
  3. from pathlib import Path
  4. sys.path.append(str(Path(__file__).parent.parent))
  5. import json
  6. import httpx
  7. from common import Logger, config_helper
  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(f"Workflow started: {data.get('data', {}).get('id')}")
  60. elif event == "node_started":
  61. node_data = data.get("data", {})
  62. log.progress(
  63. f"Node started: {node_data.get('node_type')} - {node_data.get('title')}"
  64. )
  65. elif event == "node_finished":
  66. node_data = data.get("data", {})
  67. log.progress(
  68. f"Node finished: {node_data.get('node_type')} - {node_data.get('title')}"
  69. )
  70. # Print output if it's the LLM node
  71. outputs = node_data.get("outputs", {})
  72. if outputs.get("text"):
  73. log.separator()
  74. log.info("💬 LLM Response:")
  75. log.info(outputs.get("text"), indent=2)
  76. log.separator()
  77. elif event == "workflow_finished":
  78. workflow_data = data.get("data", {})
  79. outputs = workflow_data.get("outputs", {})
  80. if outputs.get("answer"):
  81. log.separator()
  82. log.info("📤 Final Answer:")
  83. log.info(outputs.get("answer"), indent=2)
  84. log.separator()
  85. log.key_value(
  86. "Total tokens",
  87. str(workflow_data.get("total_tokens", 0)),
  88. )
  89. log.key_value(
  90. "Total steps",
  91. str(workflow_data.get("total_steps", 0)),
  92. )
  93. elif event == "error":
  94. log.error(f"Error: {data.get('message')}")
  95. except json.JSONDecodeError:
  96. # Some lines might not be JSON
  97. pass
  98. else:
  99. log.error(f"Workflow run failed with status code: {response.status_code}")
  100. log.debug(f"Response: {response.text}")
  101. else:
  102. # Handle blocking response
  103. response = client.post(
  104. run_endpoint,
  105. json=run_payload,
  106. headers=headers,
  107. )
  108. if response.status_code == 200:
  109. log.success("Workflow completed successfully!")
  110. response_data = response.json()
  111. log.separator()
  112. log.debug(f"Full response: {json.dumps(response_data, indent=2)}")
  113. # Extract the answer if available
  114. outputs = response_data.get("data", {}).get("outputs", {})
  115. if outputs.get("answer"):
  116. log.separator()
  117. log.info("📤 Final Answer:")
  118. log.info(outputs.get("answer"), indent=2)
  119. else:
  120. log.error(f"Workflow run failed with status code: {response.status_code}")
  121. log.debug(f"Response: {response.text}")
  122. except httpx.ConnectError:
  123. log.error("Could not connect to Dify API at http://localhost:5001")
  124. log.info("Make sure the API server is running with: ./dev/start-api")
  125. except httpx.TimeoutException:
  126. log.error("Request timed out")
  127. except Exception as e:
  128. log.error(f"An error occurred: {e}")
  129. if __name__ == "__main__":
  130. # Allow passing question as command line argument
  131. if len(sys.argv) > 1:
  132. question = " ".join(sys.argv[1:])
  133. else:
  134. question = "What is the capital of France?"
  135. run_workflow(question=question, streaming=True)