Tejasva commited on
Commit
3341e6c
·
1 Parent(s): 1356960

fix:minor

Browse files
README.md CHANGED
@@ -3,7 +3,8 @@ title: Code_man
3
  emoji: "🚀"
4
  colorFrom: blue
5
  colorTo: purple
6
- sdk: gradio
 
7
  app_file: app.py
8
  pinned: false
9
  ---
 
3
  emoji: "🚀"
4
  colorFrom: blue
5
  colorTo: purple
6
+ sdk: docker
7
+ app_port: 7860
8
  app_file: app.py
9
  pinned: false
10
  ---
__pycache__/app.cpython-313.pyc CHANGED
Binary files a/__pycache__/app.cpython-313.pyc and b/__pycache__/app.cpython-313.pyc differ
 
__pycache__/inference.cpython-313.pyc CHANGED
Binary files a/__pycache__/inference.cpython-313.pyc and b/__pycache__/inference.cpython-313.pyc differ
 
app.py CHANGED
@@ -3,12 +3,11 @@
3
  import os
4
  import sys
5
  import gradio as gr
6
- import json
7
  from typing import Dict, Any, Optional, List
8
  import logging
9
 
10
  from fastapi import Body, FastAPI
11
- from pydantic import BaseModel, ConfigDict
12
 
13
  # Add current directory to Python path
14
  sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
@@ -341,233 +340,212 @@ def update_ui():
341
  gr.update(visible=True)
342
  )
343
 
344
- # Create Gradio interface
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
345
  with gr.Blocks(title="CodeGuardian Environment - RL Enhanced") as demo:
346
  gr.Markdown("# 🤖 CodeGuardian Environment - RL Enhanced")
347
  gr.Markdown("Test your AI agent on code review tasks: detect issues, assess risks, and suggest fixes with reinforcement learning.")
348
-
349
  with gr.Row():
350
  reset_btn = gr.Button("🔄 Reset Environment", variant="primary")
351
  baseline_btn = gr.Button("📊 Run Baseline", variant="secondary")
352
  episode_btn = gr.Button("🎯 Run Episode", variant="secondary")
353
-
354
  with gr.Row():
355
  perf_btn = gr.Button("📈 Show Performance", variant="secondary")
356
  plot_btn = gr.Button("📊 Show Progress Plot", variant="secondary")
357
-
358
  obs_display = gr.Markdown("Click 'Reset Environment' to start")
359
-
360
- # VISUAL PERFORMANCE COMPARISON (NEW)
361
  with gr.Group(visible=True) as perf_group:
362
  gr.Markdown("## 📊 Performance Comparison")
363
  performance_display = gr.Markdown("Run baseline and episodes to see performance comparison.")
364
-
365
- # EPISODE PROGRESSION PLOT (NEW)
366
  with gr.Group(visible=True) as plot_group:
367
  gr.Markdown("## 📈 Episode Progression")
368
  progress_plot = gr.Plot(label="Score Progression")
369
-
370
  with gr.Group(visible=False) as action_group:
371
  gr.Markdown("## Take Action")
372
-
373
  with gr.Row():
374
  with gr.Column():
375
  action_type = gr.Radio(
376
  choices=["detect", "risk", "fix"],
377
  label="Action Type",
378
- value="detect"
379
  )
380
-
381
  with gr.Group(visible=True) as detect_group:
382
  detected_issues = gr.Textbox(
383
  label="Detected Issues (comma-separated)",
384
- placeholder="e.g., wrong operator, security issue, performance problem"
385
  )
386
-
387
  with gr.Group(visible=False) as risk_group:
388
  risk_level = gr.Radio(
389
  choices=["low", "medium", "high"],
390
  label="Risk Level",
391
- value="low"
392
  )
393
-
394
  with gr.Group(visible=False) as fix_group:
395
  suggested_fix = gr.Textbox(
396
  label="Suggested Fix",
397
  lines=3,
398
- placeholder="Describe or provide the fix..."
399
  )
400
-
401
  with gr.Column():
402
  step_btn = gr.Button("⚡ Execute Step", variant="primary")
403
  feedback = gr.Textbox(label="📝 Feedback", interactive=False, lines=2)
404
  reward = gr.Number(label="🏆 Reward", interactive=False)
405
-
406
- # Enhanced reward display
407
  reward_breakdown = gr.Textbox(label="📊 Reward Breakdown", interactive=False, lines=1)
408
  step_details = gr.Markdown("", label="Step Details")
409
-
410
- # Episode results display
411
  episode_results = gr.Markdown("", visible=False, label="Episode Results")
412
-
413
- # Event handlers
414
  reset_btn.click(
415
  reset_interface,
416
- outputs=obs_display
417
  ).then(
418
  update_ui,
419
- outputs=[reset_btn, baseline_btn, episode_btn, perf_btn, plot_btn, action_group, detect_group, risk_group, fix_group]
420
  )
421
-
422
  baseline_btn.click(
423
  run_baseline_interface,
424
- outputs=performance_display
425
  ).then(
426
  lambda: gr.update(visible=True),
427
- outputs=perf_group
428
  )
429
-
430
  episode_btn.click(
431
  run_episode_interface,
432
- outputs=episode_results
433
  ).then(
434
  lambda: gr.update(visible=True),
435
- outputs=episode_results
436
  ).then(
437
  get_plot_interface,
438
- outputs=progress_plot
439
  ).then(
440
  lambda: gr.update(visible=True),
441
- outputs=plot_group
442
  )
443
-
444
  perf_btn.click(
445
  get_performance_interface,
446
- outputs=performance_display
447
  ).then(
448
  lambda: gr.update(visible=True),
449
- outputs=perf_group
450
  )
451
-
452
  plot_btn.click(
453
  get_plot_interface,
454
- outputs=progress_plot
455
  ).then(
456
  lambda: gr.update(visible=True),
457
- outputs=plot_group
458
  )
459
-
460
  def toggle_action_inputs(action):
461
- """Show/hide inputs based on action type."""
462
  return (
463
  gr.update(visible=(action == "detect")),
464
  gr.update(visible=(action == "risk")),
465
- gr.update(visible=(action == "fix"))
466
  )
467
-
468
  action_type.change(
469
  toggle_action_inputs,
470
  inputs=action_type,
471
- outputs=[detect_group, risk_group, fix_group]
472
  )
473
-
474
  step_btn.click(
475
  step_interface,
476
  inputs=[action_type, detected_issues, risk_level, suggested_fix],
477
- outputs=[obs_display, feedback, reward, reward_breakdown, step_details]
478
  ).then(
479
  update_ui,
480
- outputs=[reset_btn, baseline_btn, episode_btn, perf_btn, plot_btn, action_group, detect_group, risk_group, fix_group]
481
- )
482
-
483
- # OpenEnv / TRL-style HTTP API (POST /reset, etc.) for automated Space checks.
484
- # Gradio alone does not expose these routes and returns 405 Method Not Allowed.
485
-
486
-
487
- class OpenEnvResetRequest(BaseModel):
488
- model_config = ConfigDict(extra="allow")
489
-
490
- seed: Optional[int] = None
491
- episode_id: Optional[str] = None
492
-
493
-
494
- class OpenEnvResetResponse(BaseModel):
495
- model_config = ConfigDict(extra="forbid")
496
-
497
- observation: Dict[str, Any]
498
- reward: float = 0
499
- done: bool = False
500
-
501
-
502
- class OpenEnvStepRequest(BaseModel):
503
- model_config = ConfigDict(extra="allow")
504
-
505
- action: Dict[str, Any]
506
- timeout_s: Optional[float] = None
507
- request_id: Optional[str] = None
508
-
509
-
510
- class OpenEnvStepResponse(BaseModel):
511
- model_config = ConfigDict(extra="forbid")
512
-
513
- observation: Dict[str, Any]
514
- reward: Optional[float] = None
515
- done: bool = False
516
-
517
-
518
- app = FastAPI(title="CodeGuardian OpenEnv")
519
-
520
-
521
- def _empty_openenv_observation() -> Dict[str, Any]:
522
- return Observation(
523
- code="",
524
- intent="",
525
- constraints=[],
526
- task_id="reset_error",
527
- difficulty="easy",
528
- step_index=0,
529
- ).model_dump()
530
-
531
-
532
- @app.post("/reset", response_model=OpenEnvResetResponse)
533
- async def openenv_reset(
534
- _body: OpenEnvResetRequest = Body(default_factory=OpenEnvResetRequest),
535
- ) -> OpenEnvResetResponse:
536
- try:
537
- obs = space.env.reset()
538
- space.current_obs = obs
539
- return OpenEnvResetResponse(
540
- observation=obs.model_dump(),
541
- reward=0.0,
542
- done=False,
543
- )
544
- except Exception as e:
545
- logger.error("OpenEnv POST /reset failed: %s", e, exc_info=True)
546
- return OpenEnvResetResponse(
547
- observation=_empty_openenv_observation(),
548
- reward=0.0,
549
- done=False,
550
- )
551
-
552
-
553
- @app.post("/step", response_model=OpenEnvStepResponse)
554
- async def openenv_step(request: OpenEnvStepRequest) -> OpenEnvStepResponse:
555
- action = Action.model_validate(request.action)
556
- next_obs, reward_obj, done = space.env.step(action)
557
- space.current_obs = next_obs
558
- obs_dict = next_obs.model_dump() if next_obs is not None else {}
559
- return OpenEnvStepResponse(
560
- observation=obs_dict,
561
- reward=float(reward_obj.value),
562
- done=done,
563
  )
564
 
565
-
566
- @app.get("/state")
567
- async def openenv_state() -> Dict[str, Any]:
568
- return space.env.state()
569
-
570
-
571
  demo.queue()
572
  app = gr.mount_gradio_app(app, demo, path="/")
573
 
 
3
  import os
4
  import sys
5
  import gradio as gr
 
6
  from typing import Dict, Any, Optional, List
7
  import logging
8
 
9
  from fastapi import Body, FastAPI
10
+ from pydantic import BaseModel, ConfigDict, Field
11
 
12
  # Add current directory to Python path
13
  sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
 
340
  gr.update(visible=True)
341
  )
342
 
343
+ # OpenEnv / TRL-style HTTP API — register routes on FastAPI before mounting Gradio at "/".
344
+
345
+
346
+ class OpenEnvResetRequest(BaseModel):
347
+ model_config = ConfigDict(extra="allow")
348
+
349
+ seed: Optional[int] = None
350
+ episode_id: Optional[str] = None
351
+
352
+
353
+ class OpenEnvResetResponse(BaseModel):
354
+ model_config = ConfigDict(extra="forbid")
355
+
356
+ observation: Dict[str, Any] = Field(default_factory=dict)
357
+ reward: float = 0.0
358
+ done: bool = False
359
+
360
+
361
+ class OpenEnvStepRequest(BaseModel):
362
+ model_config = ConfigDict(extra="allow")
363
+
364
+ action: Dict[str, Any]
365
+ timeout_s: Optional[float] = None
366
+ request_id: Optional[str] = None
367
+
368
+
369
+ class OpenEnvStepResponse(BaseModel):
370
+ model_config = ConfigDict(extra="forbid")
371
+
372
+ observation: Dict[str, Any] = Field(default_factory=dict)
373
+ reward: Optional[float] = None
374
+ done: bool = False
375
+
376
+
377
+ app = FastAPI(title="CodeGuardian OpenEnv")
378
+
379
+
380
+ @app.post("/reset", response_model=OpenEnvResetResponse)
381
+ async def openenv_reset(
382
+ _body: OpenEnvResetRequest = Body(default_factory=OpenEnvResetRequest),
383
+ ) -> OpenEnvResetResponse:
384
+ """OpenEnv reset check: body is always observation {}, reward 0.0, done false; env still resets."""
385
+ try:
386
+ obs = space.env.reset()
387
+ space.current_obs = obs
388
+ logger.info("OpenEnv POST /reset ok (task_id=%s)", getattr(obs, "task_id", None))
389
+ except Exception as e:
390
+ logger.error("OpenEnv POST /reset env.reset failed: %s", e, exc_info=True)
391
+ return OpenEnvResetResponse(
392
+ observation={},
393
+ reward=0.0,
394
+ done=False,
395
+ )
396
+
397
+
398
+ @app.post("/step", response_model=OpenEnvStepResponse)
399
+ async def openenv_step(request: OpenEnvStepRequest) -> OpenEnvStepResponse:
400
+ action = Action.model_validate(request.action)
401
+ next_obs, reward_obj, done = space.env.step(action)
402
+ space.current_obs = next_obs
403
+ obs_dict = next_obs.model_dump() if next_obs is not None else {}
404
+ return OpenEnvStepResponse(
405
+ observation=obs_dict,
406
+ reward=float(reward_obj.value),
407
+ done=done,
408
+ )
409
+
410
+
411
+ @app.get("/state")
412
+ async def openenv_state() -> Dict[str, Any]:
413
+ return space.env.state()
414
+
415
+
416
+ # Gradio UI — built after API routes; mounted last so /reset, /step, /state stay reachable.
417
  with gr.Blocks(title="CodeGuardian Environment - RL Enhanced") as demo:
418
  gr.Markdown("# 🤖 CodeGuardian Environment - RL Enhanced")
419
  gr.Markdown("Test your AI agent on code review tasks: detect issues, assess risks, and suggest fixes with reinforcement learning.")
420
+
421
  with gr.Row():
422
  reset_btn = gr.Button("🔄 Reset Environment", variant="primary")
423
  baseline_btn = gr.Button("📊 Run Baseline", variant="secondary")
424
  episode_btn = gr.Button("🎯 Run Episode", variant="secondary")
425
+
426
  with gr.Row():
427
  perf_btn = gr.Button("📈 Show Performance", variant="secondary")
428
  plot_btn = gr.Button("📊 Show Progress Plot", variant="secondary")
429
+
430
  obs_display = gr.Markdown("Click 'Reset Environment' to start")
431
+
 
432
  with gr.Group(visible=True) as perf_group:
433
  gr.Markdown("## 📊 Performance Comparison")
434
  performance_display = gr.Markdown("Run baseline and episodes to see performance comparison.")
435
+
 
436
  with gr.Group(visible=True) as plot_group:
437
  gr.Markdown("## 📈 Episode Progression")
438
  progress_plot = gr.Plot(label="Score Progression")
439
+
440
  with gr.Group(visible=False) as action_group:
441
  gr.Markdown("## Take Action")
442
+
443
  with gr.Row():
444
  with gr.Column():
445
  action_type = gr.Radio(
446
  choices=["detect", "risk", "fix"],
447
  label="Action Type",
448
+ value="detect",
449
  )
450
+
451
  with gr.Group(visible=True) as detect_group:
452
  detected_issues = gr.Textbox(
453
  label="Detected Issues (comma-separated)",
454
+ placeholder="e.g., wrong operator, security issue, performance problem",
455
  )
456
+
457
  with gr.Group(visible=False) as risk_group:
458
  risk_level = gr.Radio(
459
  choices=["low", "medium", "high"],
460
  label="Risk Level",
461
+ value="low",
462
  )
463
+
464
  with gr.Group(visible=False) as fix_group:
465
  suggested_fix = gr.Textbox(
466
  label="Suggested Fix",
467
  lines=3,
468
+ placeholder="Describe or provide the fix...",
469
  )
470
+
471
  with gr.Column():
472
  step_btn = gr.Button("⚡ Execute Step", variant="primary")
473
  feedback = gr.Textbox(label="📝 Feedback", interactive=False, lines=2)
474
  reward = gr.Number(label="🏆 Reward", interactive=False)
475
+
 
476
  reward_breakdown = gr.Textbox(label="📊 Reward Breakdown", interactive=False, lines=1)
477
  step_details = gr.Markdown("", label="Step Details")
478
+
 
479
  episode_results = gr.Markdown("", visible=False, label="Episode Results")
480
+
 
481
  reset_btn.click(
482
  reset_interface,
483
+ outputs=obs_display,
484
  ).then(
485
  update_ui,
486
+ outputs=[reset_btn, baseline_btn, episode_btn, perf_btn, plot_btn, action_group, detect_group, risk_group, fix_group],
487
  )
488
+
489
  baseline_btn.click(
490
  run_baseline_interface,
491
+ outputs=performance_display,
492
  ).then(
493
  lambda: gr.update(visible=True),
494
+ outputs=perf_group,
495
  )
496
+
497
  episode_btn.click(
498
  run_episode_interface,
499
+ outputs=episode_results,
500
  ).then(
501
  lambda: gr.update(visible=True),
502
+ outputs=episode_results,
503
  ).then(
504
  get_plot_interface,
505
+ outputs=progress_plot,
506
  ).then(
507
  lambda: gr.update(visible=True),
508
+ outputs=plot_group,
509
  )
510
+
511
  perf_btn.click(
512
  get_performance_interface,
513
+ outputs=performance_display,
514
  ).then(
515
  lambda: gr.update(visible=True),
516
+ outputs=perf_group,
517
  )
518
+
519
  plot_btn.click(
520
  get_plot_interface,
521
+ outputs=progress_plot,
522
  ).then(
523
  lambda: gr.update(visible=True),
524
+ outputs=plot_group,
525
  )
526
+
527
  def toggle_action_inputs(action):
 
528
  return (
529
  gr.update(visible=(action == "detect")),
530
  gr.update(visible=(action == "risk")),
531
+ gr.update(visible=(action == "fix")),
532
  )
533
+
534
  action_type.change(
535
  toggle_action_inputs,
536
  inputs=action_type,
537
+ outputs=[detect_group, risk_group, fix_group],
538
  )
539
+
540
  step_btn.click(
541
  step_interface,
542
  inputs=[action_type, detected_issues, risk_level, suggested_fix],
543
+ outputs=[obs_display, feedback, reward, reward_breakdown, step_details],
544
  ).then(
545
  update_ui,
546
+ outputs=[reset_btn, baseline_btn, episode_btn, perf_btn, plot_btn, action_group, detect_group, risk_group, fix_group],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
547
  )
548
 
 
 
 
 
 
 
549
  demo.queue()
550
  app = gr.mount_gradio_app(app, demo, path="/")
551
 
inference.py CHANGED
@@ -26,6 +26,85 @@ DEFAULT_MODEL_NAME = "meta-llama/Meta-Llama-3-8B-Instruct"
26
  HF_FALLBACK_MODEL = "mistralai/Mistral-7B-Instruct-v0.2"
27
 
28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  def _fallback_llm_json_string(reason: str = "LLM unavailable") -> str:
30
  return json.dumps(
31
  {
@@ -46,17 +125,29 @@ def setup_openai_client() -> tuple[OpenAI, str]:
46
 
47
  api_base_url = os.getenv("API_BASE_URL", DEFAULT_API_BASE_URL)
48
  model_name = os.getenv("MODEL_NAME", DEFAULT_MODEL_NAME)
49
- hf_token = os.getenv("HF_TOKEN") or os.getenv("HUGGINGFACEHUB_API_TOKEN")
 
 
 
 
 
 
 
 
 
50
 
51
  print(f"DEBUG: API_BASE_URL={api_base_url}")
52
  print(f"DEBUG: MODEL_NAME={model_name}")
53
- logger.info("HF OpenAI-compatible client: API_BASE_URL=%s MODEL_NAME=%s", api_base_url, model_name)
54
-
55
- if not hf_token:
56
- raise ValueError("Set HF_TOKEN or HUGGINGFACEHUB_API_TOKEN for Hugging Face API access")
 
 
 
57
 
58
  client = OpenAI(
59
- api_key=hf_token,
60
  base_url=api_base_url,
61
  )
62
 
 
26
  HF_FALLBACK_MODEL = "mistralai/Mistral-7B-Instruct-v0.2"
27
 
28
 
29
+ def _hf_auth_tokens() -> Optional[str]:
30
+ return os.getenv("HF_TOKEN") or os.getenv("HUGGINGFACEHUB_API_TOKEN")
31
+
32
+
33
+ def _openai_auth_tokens() -> Optional[str]:
34
+ return os.getenv("OPENAI_API_KEY") or os.getenv("API_KEY")
35
+
36
+
37
+ def _looks_like_huggingface_endpoint(url: str) -> bool:
38
+ u = (url or "").lower()
39
+ return any(x in u for x in ("huggingface", "hf.co", "router.huggingface"))
40
+
41
+
42
+ def _looks_like_openai_endpoint(url: str) -> bool:
43
+ return "openai.com" in (url or "").lower()
44
+
45
+
46
+ def _looks_like_hf_hub_model(model: str) -> bool:
47
+ """Hugging Face router / Inference typically uses org/model ids."""
48
+ return "/" in (model or "").strip()
49
+
50
+
51
+ def _looks_like_openai_model(model: str) -> bool:
52
+ m = (model or "").strip().lower()
53
+ if not m or "/" in m:
54
+ return False
55
+ prefixes = (
56
+ "gpt-",
57
+ "o1",
58
+ "o3",
59
+ "o4",
60
+ "ft:",
61
+ "davinci",
62
+ "text-embedding",
63
+ "chatgpt-",
64
+ )
65
+ return any(m.startswith(p) for p in prefixes)
66
+
67
+
68
+ def _resolve_api_key(api_base_url: str, model_name: str) -> str:
69
+ """
70
+ Pick API key for an OpenAI-compatible client: Hugging Face token and/or OpenAI key,
71
+ ordered from URL + model hints, with 'or' fallbacks so either stack can work.
72
+ """
73
+ hf_key = _hf_auth_tokens()
74
+ oai_key = _openai_auth_tokens()
75
+
76
+ url_hf = _looks_like_huggingface_endpoint(api_base_url)
77
+ url_oai = _looks_like_openai_endpoint(api_base_url)
78
+ model_hf = _looks_like_hf_hub_model(model_name)
79
+ model_oai = _looks_like_openai_model(model_name)
80
+
81
+ prefer_hf = url_hf or model_hf
82
+ prefer_oai = url_oai or model_oai
83
+
84
+ key: Optional[str] = None
85
+ if prefer_hf and not prefer_oai:
86
+ key = hf_key or oai_key
87
+ elif prefer_oai and not prefer_hf:
88
+ key = oai_key or hf_key
89
+ elif prefer_hf and prefer_oai:
90
+ if url_hf and not url_oai:
91
+ key = hf_key or oai_key
92
+ elif url_oai and not url_hf:
93
+ key = oai_key or hf_key
94
+ else:
95
+ key = hf_key or oai_key
96
+ else:
97
+ key = hf_key or oai_key
98
+
99
+ if not key:
100
+ raise ValueError(
101
+ "Set authentication for your provider: "
102
+ "(HF_TOKEN or HUGGINGFACEHUB_API_TOKEN) for Hugging Face, "
103
+ "or (OPENAI_API_KEY or API_KEY) for OpenAI"
104
+ )
105
+ return key
106
+
107
+
108
  def _fallback_llm_json_string(reason: str = "LLM unavailable") -> str:
109
  return json.dumps(
110
  {
 
125
 
126
  api_base_url = os.getenv("API_BASE_URL", DEFAULT_API_BASE_URL)
127
  model_name = os.getenv("MODEL_NAME", DEFAULT_MODEL_NAME)
128
+ api_key = _resolve_api_key(api_base_url, model_name)
129
+
130
+ hf_key = _hf_auth_tokens()
131
+ oai_key = _openai_auth_tokens()
132
+ if api_key == hf_key and hf_key:
133
+ auth_label = "Hugging Face token (HF_TOKEN / HUGGINGFACEHUB_API_TOKEN)"
134
+ elif api_key == oai_key and oai_key:
135
+ auth_label = "OpenAI key (OPENAI_API_KEY / API_KEY)"
136
+ else:
137
+ auth_label = "resolved API key"
138
 
139
  print(f"DEBUG: API_BASE_URL={api_base_url}")
140
  print(f"DEBUG: MODEL_NAME={model_name}")
141
+ print(f"DEBUG: auth={auth_label}")
142
+ logger.info(
143
+ "OpenAI-compatible client: API_BASE_URL=%s MODEL_NAME=%s auth=%s",
144
+ api_base_url,
145
+ model_name,
146
+ auth_label,
147
+ )
148
 
149
  client = OpenAI(
150
+ api_key=api_key,
151
  base_url=api_base_url,
152
  )
153
 
requirements.txt CHANGED
@@ -1,10 +1,13 @@
1
- pydantic>=2.0.0
 
 
 
2
  openai>=1.0.0
 
 
3
  gymnasium>=0.28.0
4
  numpy>=1.24.0
5
  python-dotenv>=1.0.0
6
  flask>=3.0.0
7
- fastapi>=0.110.0
8
- uvicorn[standard]>=0.27.0
9
- gradio>=4.0.0
10
- plotly
 
1
+ # Hugging Face Space / OpenEnv server (required)
2
+ fastapi>=0.110.0
3
+ uvicorn[standard]>=0.27.0
4
+ gradio>=4.0.0
5
  openai>=1.0.0
6
+
7
+ pydantic>=2.0.0
8
  gymnasium>=0.28.0
9
  numpy>=1.24.0
10
  python-dotenv>=1.0.0
11
  flask>=3.0.0
12
+ plotly
13
+ pandas