GitHub Bot commited on
Commit
35db168
·
1 Parent(s): cc1daf4

Update to use DashScope credentials securely via environment variables

Browse files

- Modified config.py to load credentials from DASHSCOPE_API_KEY and DASHSCOPE_BASE_URL env vars
- Updated setup_space.py to set HF Space secrets via API without exposing keys in logs
- Updated env_loader.py to validate DashScope credentials securely
- Removed hardcoded API keys from configuration
- Added function to set HF Space secrets programmatically

Files changed (5) hide show
  1. README.md +0 -10
  2. base_agent.py +2 -2
  3. config.py +15 -13
  4. env_loader.py +28 -11
  5. setup_space.py +93 -11
README.md DELETED
@@ -1,10 +0,0 @@
1
- ---
2
- title: Multi Agent System
3
- emoji: 📉
4
- colorFrom: indigo
5
- colorTo: red
6
- sdk: docker
7
- pinned: false
8
- ---
9
-
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
base_agent.py CHANGED
@@ -26,7 +26,7 @@ class BaseAgent:
26
  self.agent_name = agent_name
27
  self.system_prompt = system_prompt
28
 
29
- # Initialize OpenRouter client
30
  self.client = OpenAI(
31
  api_key=settings.openrouter_api_key,
32
  base_url=settings.openrouter_base_url,
@@ -53,7 +53,7 @@ class BaseAgent:
53
  logger.info(f"{self.agent_name}: Processing inputs")
54
 
55
  try:
56
- # Call OpenRouter API via OpenAI client
57
  response = self.client.chat.completions.create(
58
  model=settings.model_name,
59
  messages=[
 
26
  self.agent_name = agent_name
27
  self.system_prompt = system_prompt
28
 
29
+ # Initialize DashScope client (OpenAI-compatible API)
30
  self.client = OpenAI(
31
  api_key=settings.openrouter_api_key,
32
  base_url=settings.openrouter_base_url,
 
53
  logger.info(f"{self.agent_name}: Processing inputs")
54
 
55
  try:
56
+ # Call DashScope API via OpenAI client
57
  response = self.client.chat.completions.create(
58
  model=settings.model_name,
59
  messages=[
config.py CHANGED
@@ -14,10 +14,10 @@ validate_on_startup()
14
  class Settings(BaseSettings):
15
  """Application settings loaded from environment variables."""
16
 
17
- # OpenRouter Configuration
18
  openrouter_api_key: str = ""
19
- openrouter_base_url: str = "https://openrouter.ai/api/v1"
20
- model_name: str = "poolside/laguna-m.1:free"
21
 
22
  # Hugging Face Configuration
23
  huggingface_token: str = ""
@@ -52,22 +52,24 @@ class Settings(BaseSettings):
52
  protected_namespaces = ('settings_',) # Allow model_ namespace
53
 
54
  def __init__(self, **data):
55
- # Load from environment with fallbacks
56
  if not data.get("openrouter_api_key"):
57
- data["openrouter_api_key"] = os.getenv("OPENROUTER_API_KEY", "")
58
- if not data.get("huggingface_token"):
59
- data["huggingface_token"] = os.getenv("HUGGINGFACE_TOKEN", "")
60
- if not data.get("huggingface_dataset"):
61
- data["huggingface_dataset"] = os.getenv(
62
- "HUGGINGFACE_DATASET", "factorstudios/Pipeline"
63
- )
64
  if not data.get("openrouter_base_url"):
65
  data["openrouter_base_url"] = os.getenv(
66
- "OPENROUTER_BASE_URL", "https://openrouter.ai/api/v1"
67
  )
68
  if not data.get("model_name"):
69
  data["model_name"] = os.getenv(
70
- "MODEL_NAME", "poolside/laguna-m.1:free"
 
 
 
 
 
 
 
 
71
  )
72
 
73
  super().__init__(**data)
 
14
  class Settings(BaseSettings):
15
  """Application settings loaded from environment variables."""
16
 
17
+ # DashScope Configuration (Aliyun Qwen) - loaded from environment
18
  openrouter_api_key: str = ""
19
+ openrouter_base_url: str = ""
20
+ model_name: str = "qwen3.7-plus"
21
 
22
  # Hugging Face Configuration
23
  huggingface_token: str = ""
 
52
  protected_namespaces = ('settings_',) # Allow model_ namespace
53
 
54
  def __init__(self, **data):
55
+ # Load DashScope credentials from environment
56
  if not data.get("openrouter_api_key"):
57
+ data["openrouter_api_key"] = os.getenv("DASHSCOPE_API_KEY", "")
 
 
 
 
 
 
58
  if not data.get("openrouter_base_url"):
59
  data["openrouter_base_url"] = os.getenv(
60
+ "DASHSCOPE_BASE_URL", "https://dashscope.aliyuncs.com/compatible-mode/v1"
61
  )
62
  if not data.get("model_name"):
63
  data["model_name"] = os.getenv(
64
+ "MODEL_NAME", "qwen3.7-plus"
65
+ )
66
+
67
+ # Load Hugging Face configuration
68
+ if not data.get("huggingface_token"):
69
+ data["huggingface_token"] = os.getenv("HUGGINGFACE_TOKEN", "")
70
+ if not data.get("huggingface_dataset"):
71
+ data["huggingface_dataset"] = os.getenv(
72
+ "HUGGINGFACE_DATASET", "factorstudios/Pipeline"
73
  )
74
 
75
  super().__init__(**data)
env_loader.py CHANGED
@@ -48,13 +48,16 @@ class EnvironmentLoader:
48
  True if all required secrets are present, False otherwise
49
  """
50
  required_secrets = [
51
- "OPENROUTER_API_KEY",
52
  "HUGGINGFACE_TOKEN",
53
  ]
54
 
 
 
 
 
 
55
  optional_secrets = [
56
  "HUGGINGFACE_DATASET",
57
- "OPENROUTER_BASE_URL",
58
  "MODEL_NAME",
59
  ]
60
 
@@ -67,16 +70,30 @@ class EnvironmentLoader:
67
  logger.error(f"Missing required secret: {secret}")
68
  all_valid = False
69
  else:
70
- # Log masked value for debugging
71
- masked = value[:10] + "..." if len(value) > 10 else "***"
72
- logger.info(f"✓ {secret} configured ({masked})")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
 
74
  # Check optional secrets
75
  for secret in optional_secrets:
76
  value = os.getenv(secret)
77
  if value:
78
- masked = value[:10] + "..." if len(value) > 10 else "***"
79
- logger.info(f"✓ {secret} configured ({masked})")
80
  else:
81
  logger.info(f"ℹ {secret} not configured (using default)")
82
 
@@ -90,12 +107,12 @@ class EnvironmentLoader:
90
  Dictionary with API configuration
91
  """
92
  return {
93
- "openrouter_api_key": EnvironmentLoader.get_secret("OPENROUTER_API_KEY"),
94
  "openrouter_base_url": os.getenv(
95
- "OPENROUTER_BASE_URL", "https://openrouter.ai/api/v1"
96
  ),
97
- "model_name": os.getenv("MODEL_NAME", "poolside/laguna-m.1:free"),
98
- "huggingface_token": EnvironmentLoader.get_secret("HUGGINGFACE_TOKEN"),
99
  "huggingface_dataset": os.getenv(
100
  "HUGGINGFACE_DATASET", "factorstudios/Pipeline"
101
  ),
 
48
  True if all required secrets are present, False otherwise
49
  """
50
  required_secrets = [
 
51
  "HUGGINGFACE_TOKEN",
52
  ]
53
 
54
+ dashscope_secrets = [
55
+ "DASHSCOPE_API_KEY",
56
+ "DASHSCOPE_BASE_URL",
57
+ ]
58
+
59
  optional_secrets = [
60
  "HUGGINGFACE_DATASET",
 
61
  "MODEL_NAME",
62
  ]
63
 
 
70
  logger.error(f"Missing required secret: {secret}")
71
  all_valid = False
72
  else:
73
+ logger.info(f"✓ {secret} configured")
74
+
75
+ # Check DashScope secrets (without exposing values)
76
+ logger.info("\nDashScope Configuration:")
77
+ dashscope_valid = True
78
+ for secret in dashscope_secrets:
79
+ value = os.getenv(secret)
80
+ if value:
81
+ logger.info(f"✓ {secret} configured (***hidden***)")
82
+ else:
83
+ logger.warning(f"âš  {secret} not configured")
84
+ dashscope_valid = False
85
+
86
+ if not dashscope_valid:
87
+ logger.warning(
88
+ "\nâš  DashScope credentials not fully configured. "
89
+ "They will be set via HF API during Space deployment."
90
+ )
91
 
92
  # Check optional secrets
93
  for secret in optional_secrets:
94
  value = os.getenv(secret)
95
  if value:
96
+ logger.info(f"✓ {secret} configured")
 
97
  else:
98
  logger.info(f"ℹ {secret} not configured (using default)")
99
 
 
107
  Dictionary with API configuration
108
  """
109
  return {
110
+ "openrouter_api_key": os.getenv("DASHSCOPE_API_KEY", ""),
111
  "openrouter_base_url": os.getenv(
112
+ "DASHSCOPE_BASE_URL", "https://dashscope.aliyuncs.com/compatible-mode/v1"
113
  ),
114
+ "model_name": os.getenv("MODEL_NAME", "qwen3.7-plus"),
115
+ "huggingface_token": os.getenv("HUGGINGFACE_TOKEN", ""),
116
  "huggingface_dataset": os.getenv(
117
  "HUGGINGFACE_DATASET", "factorstudios/Pipeline"
118
  ),
setup_space.py CHANGED
@@ -2,6 +2,7 @@
2
  import os
3
  import sys
4
  import logging
 
5
  from pathlib import Path
6
 
7
 
@@ -18,16 +19,73 @@ def check_environment():
18
  return is_hf_space
19
 
20
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  def validate_secrets():
22
  """Validate that required secrets are configured."""
23
  required_secrets = [
24
- "OPENROUTER_API_KEY",
25
  "HUGGINGFACE_TOKEN",
26
  ]
27
 
 
 
 
 
 
28
  optional_secrets = [
29
  "HUGGINGFACE_DATASET",
30
- "OPENROUTER_BASE_URL",
31
  "MODEL_NAME",
32
  ]
33
 
@@ -44,15 +102,24 @@ def validate_secrets():
44
  logger.error(f"✗ MISSING: {secret}")
45
  missing_secrets.append(secret)
46
  else:
47
- masked = value[:10] + "..." if len(value) > 10 else "***"
48
- logger.info(f"✓ CONFIGURED: {secret} ({masked})")
 
 
 
 
 
 
 
 
 
 
49
 
50
  # Check optional secrets
51
  for secret in optional_secrets:
52
  value = os.getenv(secret)
53
  if value:
54
- masked = value[:10] + "..." if len(value) > 10 else "***"
55
- logger.info(f"✓ CONFIGURED: {secret} ({masked})")
56
  else:
57
  logger.info(f"ℹ NOT SET: {secret} (using default)")
58
 
@@ -66,7 +133,11 @@ def validate_secrets():
66
  logger.error("3. Add each missing secret")
67
  return False
68
 
69
- logger.info("\n✅ All required secrets are configured!")
 
 
 
 
70
  return True
71
 
72
 
@@ -100,16 +171,20 @@ def print_deployment_info():
100
  logger.info("ℹ Not running in Hugging Face Space")
101
  logger.info("ℹ Running locally or in different environment")
102
 
103
- logger.info(f"✓ Model: {os.getenv('MODEL_NAME', 'poolside/laguna-m.1:free')}")
104
- logger.info(f"✓ Dataset: {os.getenv('HUGGINGFACE_DATASET', 'factorstudios/Pipeline')}")
105
- logger.info(f"✓ Port: {os.getenv('PORT', '7860')}")
 
 
 
 
106
 
107
  logger.info("\n" + "=" * 60)
108
  logger.info("API Endpoints")
109
  logger.info("=" * 60)
110
  logger.info("Health: GET /health")
111
  logger.info("Docs: GET /docs")
112
- logger.info("Pipeline: POST /api/v1/pipeline/execute")
113
  logger.info("=" * 60)
114
 
115
 
@@ -117,12 +192,19 @@ def main():
117
  """Run setup checks."""
118
  logger.info("Starting Hugging Face Space setup...\n")
119
 
 
 
 
120
  # Check environment
121
  is_hf_space = check_environment()
122
 
123
  # Validate secrets
124
  secrets_valid = validate_secrets()
125
 
 
 
 
 
126
  # Create directories
127
  create_directories()
128
 
 
2
  import os
3
  import sys
4
  import logging
5
+ import requests
6
  from pathlib import Path
7
 
8
 
 
19
  return is_hf_space
20
 
21
 
22
+ def set_hf_space_secrets(hf_token):
23
+ """Set DashScope credentials as HF Space secrets via API.
24
+
25
+ Args:
26
+ hf_token: Hugging Face API token
27
+
28
+ Returns:
29
+ bool: True if secrets were set successfully
30
+ """
31
+ space_id = os.getenv("SPACE_ID")
32
+ if not space_id:
33
+ logger.info("ℹ Not running in HF Space (no SPACE_ID). Skipping secret configuration.")
34
+ return True
35
+
36
+ dashscope_key = os.getenv("DASHSCOPE_API_KEY")
37
+ dashscope_url = os.getenv("DASHSCOPE_BASE_URL")
38
+
39
+ if not dashscope_key or not dashscope_url:
40
+ logger.warning("ℹ DashScope credentials not found in environment. Skipping HF secret setup.")
41
+ return True
42
+
43
+ logger.info("Setting up HF Space secrets via API...")
44
+
45
+ headers = {
46
+ "Authorization": f"Bearer {hf_token}",
47
+ "Content-Type": "application/json",
48
+ }
49
+
50
+ secrets = [
51
+ ("DASHSCOPE_API_KEY", dashscope_key),
52
+ ("DASHSCOPE_BASE_URL", dashscope_url),
53
+ ]
54
+
55
+ for secret_name, secret_value in secrets:
56
+ try:
57
+ url = f"https://huggingface.co/api/spaces/{space_id}/secrets"
58
+ payload = {
59
+ "key": secret_name,
60
+ "value": secret_value,
61
+ }
62
+
63
+ response = requests.post(url, json=payload, headers=headers, timeout=10)
64
+
65
+ if response.status_code in [200, 201]:
66
+ logger.info(f"✓ Secret '{secret_name}' set successfully")
67
+ else:
68
+ logger.warning(f"âš  Failed to set '{secret_name}': {response.status_code}")
69
+
70
+ except Exception as e:
71
+ logger.warning(f"âš  Error setting secret '{secret_name}': {e}")
72
+
73
+ return True
74
+
75
+
76
  def validate_secrets():
77
  """Validate that required secrets are configured."""
78
  required_secrets = [
 
79
  "HUGGINGFACE_TOKEN",
80
  ]
81
 
82
+ dashscope_secrets = [
83
+ "DASHSCOPE_API_KEY",
84
+ "DASHSCOPE_BASE_URL",
85
+ ]
86
+
87
  optional_secrets = [
88
  "HUGGINGFACE_DATASET",
 
89
  "MODEL_NAME",
90
  ]
91
 
 
102
  logger.error(f"✗ MISSING: {secret}")
103
  missing_secrets.append(secret)
104
  else:
105
+ logger.info(f"✓ CONFIGURED: {secret}")
106
+
107
+ # Check DashScope secrets (log without exposing values)
108
+ logger.info("\nDashScope Configuration:")
109
+ dashscope_configured = True
110
+ for secret in dashscope_secrets:
111
+ value = os.getenv(secret)
112
+ if value:
113
+ logger.info(f"✓ CONFIGURED: {secret} (***hidden***)")
114
+ else:
115
+ logger.info(f"ℹ NOT SET: {secret}")
116
+ dashscope_configured = False
117
 
118
  # Check optional secrets
119
  for secret in optional_secrets:
120
  value = os.getenv(secret)
121
  if value:
122
+ logger.info(f"✓ CONFIGURED: {secret}")
 
123
  else:
124
  logger.info(f"ℹ NOT SET: {secret} (using default)")
125
 
 
133
  logger.error("3. Add each missing secret")
134
  return False
135
 
136
+ if not dashscope_configured:
137
+ logger.warning("\nâš  DashScope credentials not fully configured")
138
+ logger.warning("The system will attempt to set them via HF API during deployment")
139
+
140
+ logger.info("\n✅ Required secrets are configured!")
141
  return True
142
 
143
 
 
171
  logger.info("ℹ Not running in Hugging Face Space")
172
  logger.info("ℹ Running locally or in different environment")
173
 
174
+ model = os.getenv("MODEL_NAME", "qwen3.7-plus")
175
+ dataset = os.getenv("HUGGINGFACE_DATASET", "factorstudios/Pipeline")
176
+ port = os.getenv("PORT", "7860")
177
+
178
+ logger.info(f"✓ Model: {model}")
179
+ logger.info(f"✓ Dataset: {dataset}")
180
+ logger.info(f"✓ Port: {port}")
181
 
182
  logger.info("\n" + "=" * 60)
183
  logger.info("API Endpoints")
184
  logger.info("=" * 60)
185
  logger.info("Health: GET /health")
186
  logger.info("Docs: GET /docs")
187
+ logger.info("Pipeline: POST /api/pipeline/execute")
188
  logger.info("=" * 60)
189
 
190
 
 
192
  """Run setup checks."""
193
  logger.info("Starting Hugging Face Space setup...\n")
194
 
195
+ # Get HF token from environment
196
+ hf_token = os.getenv("HUGGINGFACE_TOKEN")
197
+
198
  # Check environment
199
  is_hf_space = check_environment()
200
 
201
  # Validate secrets
202
  secrets_valid = validate_secrets()
203
 
204
+ # Set HF Space secrets via API if running in Space
205
+ if hf_token and is_hf_space:
206
+ set_hf_space_secrets(hf_token)
207
+
208
  # Create directories
209
  create_directories()
210