SeaWolf-AI commited on
Commit
5b119b6
·
verified ·
1 Parent(s): a1fedd9

feat: switch to Fireworks AI API with Kimi K2.5 model

Browse files
Files changed (3) hide show
  1. README.md +2 -3
  2. app.py +53 -34
  3. requirements.txt +1 -1
README.md CHANGED
@@ -27,6 +27,5 @@ Set the following environment variables in your Space settings:
27
 
28
  | Variable | Description | Default |
29
  |----------|-------------|---------|
30
- | `OPENAI_API_KEY` | API key for the LLM provider | (required) |
31
- | `OPENAI_BASE_URL` | Base URL for the API endpoint | `https://openrouter.ai/api/v1` |
32
- | `OPENAI_MODEL` | Model to use | `anthropic/claude-sonnet-4` |
 
27
 
28
  | Variable | Description | Default |
29
  |----------|-------------|---------|
30
+ | `FIREWORKS_API_KEY` | Fireworks AI API key | (required) |
31
+ | `FIREWORKS_MODEL` | Model to use | `accounts/fireworks/models/kimi-k2p5` |
 
app.py CHANGED
@@ -2,11 +2,12 @@
2
  Hermes Agent - Data Analysis Demo for Hugging Face Spaces.
3
 
4
  Provides a Gradio web UI with:
5
- 1. AI Chat tab - converse with an LLM via OpenAI-compatible API
6
  2. Data Analysis tab - upload CSV/JSON, ask questions, get charts & stats
7
  """
8
 
9
  import io
 
10
  import os
11
  import re
12
  import uuid
@@ -18,14 +19,14 @@ import matplotlib
18
  matplotlib.use("Agg")
19
  import matplotlib.pyplot as plt
20
  import plotly.express as px
21
- from openai import OpenAI
22
 
23
  # ---------------------------------------------------------------------------
24
- # Configuration
25
  # ---------------------------------------------------------------------------
26
- API_KEY = os.getenv("OPENAI_API_KEY", "")
27
- BASE_URL = os.getenv("OPENAI_BASE_URL", "https://openrouter.ai/api/v1")
28
- MODEL = os.getenv("OPENAI_MODEL", "anthropic/claude-sonnet-4")
29
 
30
  SYSTEM_PROMPT = """You are Hermes, an expert data analyst AI assistant built by Nous Research.
31
  You help users analyze data, create visualizations, and extract insights.
@@ -63,37 +64,59 @@ Respond with:
63
  - Uses plt.close() after saving"""
64
 
65
 
66
- def get_client() -> OpenAI:
67
- """Create an OpenAI client with current settings."""
68
- return OpenAI(api_key=API_KEY, base_url=BASE_URL)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
 
70
 
71
  # ---------------------------------------------------------------------------
72
  # Chat Tab
73
  # ---------------------------------------------------------------------------
74
  def chat_respond(message: str, history: list[dict], session_id: str):
75
- """Stream a chat response from the LLM."""
76
- if not API_KEY:
77
- yield "Please set the `OPENAI_API_KEY` environment variable in your Space settings."
78
  return
79
 
80
- client = get_client()
81
  messages = [{"role": "system", "content": SYSTEM_PROMPT}]
82
  for entry in history:
83
  messages.append({"role": entry["role"], "content": entry["content"]})
84
  messages.append({"role": "user", "content": message})
85
 
86
  try:
87
- stream = client.chat.completions.create(
88
- model=MODEL,
89
- messages=messages,
90
- stream=True,
91
- max_tokens=4096,
92
- extra_headers={"X-Hermes-Session-Id": session_id},
93
- )
94
  partial = ""
95
- for chunk in stream:
96
- delta = chunk.choices[0].delta.content
 
 
 
 
 
 
97
  if delta:
98
  partial += delta
99
  yield partial
@@ -171,8 +194,8 @@ def analyze_data(
171
  file, question: str, history: list[dict]
172
  ) -> tuple[list[dict], str, str | None, str]:
173
  """Main analysis pipeline: upload data, ask question, get results."""
174
- if not API_KEY:
175
- msg = "Please set the `OPENAI_API_KEY` environment variable."
176
  return history + [{"role": "assistant", "content": msg}], "", None, ""
177
 
178
  df, summary_md = load_data(file)
@@ -206,19 +229,16 @@ def analyze_data(
206
  question=question,
207
  )
208
 
209
- client = get_client()
210
  messages = [{"role": "system", "content": SYSTEM_PROMPT}]
211
  for entry in history:
212
  messages.append({"role": entry["role"], "content": entry["content"]})
213
  messages.append({"role": "user", "content": prompt})
214
 
215
  try:
216
- response = client.chat.completions.create(
217
- model=MODEL,
218
- messages=messages,
219
- max_tokens=4096,
220
- )
221
- answer = response.choices[0].message.content or ""
222
  except Exception as e:
223
  answer = f"API Error: {e}"
224
  return (
@@ -373,9 +393,8 @@ Set these environment variables in your Space settings:
373
 
374
  | Variable | Description |
375
  |----------|-------------|
376
- | `OPENAI_API_KEY` | Your API key |
377
- | `OPENAI_BASE_URL` | API endpoint (default: OpenRouter) |
378
- | `OPENAI_MODEL` | Model name (default: anthropic/claude-sonnet-4) |
379
 
380
  ### Links
381
  - [GitHub Repository](https://github.com/NousResearch/hermes-agent)
 
2
  Hermes Agent - Data Analysis Demo for Hugging Face Spaces.
3
 
4
  Provides a Gradio web UI with:
5
+ 1. AI Chat tab - converse with Kimi K2.5 via Fireworks AI
6
  2. Data Analysis tab - upload CSV/JSON, ask questions, get charts & stats
7
  """
8
 
9
  import io
10
+ import json
11
  import os
12
  import re
13
  import uuid
 
19
  matplotlib.use("Agg")
20
  import matplotlib.pyplot as plt
21
  import plotly.express as px
22
+ import requests as http_requests
23
 
24
  # ---------------------------------------------------------------------------
25
+ # Configuration - Fireworks AI with Kimi K2.5
26
  # ---------------------------------------------------------------------------
27
+ FIREWORKS_API_KEY = os.getenv("FIREWORKS_API_KEY", "")
28
+ FIREWORKS_URL = "https://api.fireworks.ai/inference/v1/chat/completions"
29
+ MODEL = os.getenv("FIREWORKS_MODEL", "accounts/fireworks/models/kimi-k2p5")
30
 
31
  SYSTEM_PROMPT = """You are Hermes, an expert data analyst AI assistant built by Nous Research.
32
  You help users analyze data, create visualizations, and extract insights.
 
64
  - Uses plt.close() after saving"""
65
 
66
 
67
+ def fireworks_chat(messages: list[dict], stream: bool = False):
68
+ """Call Fireworks AI API with the given messages."""
69
+ headers = {
70
+ "Accept": "application/json",
71
+ "Content-Type": "application/json",
72
+ "Authorization": f"Bearer {FIREWORKS_API_KEY}",
73
+ }
74
+ payload = {
75
+ "model": MODEL,
76
+ "max_tokens": 4096,
77
+ "top_p": 1,
78
+ "top_k": 40,
79
+ "presence_penalty": 0,
80
+ "frequency_penalty": 0,
81
+ "temperature": 0.6,
82
+ "messages": messages,
83
+ "stream": stream,
84
+ }
85
+ return http_requests.post(
86
+ FIREWORKS_URL,
87
+ headers=headers,
88
+ json=payload,
89
+ stream=stream,
90
+ timeout=120,
91
+ )
92
 
93
 
94
  # ---------------------------------------------------------------------------
95
  # Chat Tab
96
  # ---------------------------------------------------------------------------
97
  def chat_respond(message: str, history: list[dict], session_id: str):
98
+ """Stream a chat response from Fireworks AI (Kimi K2.5)."""
99
+ if not FIREWORKS_API_KEY:
100
+ yield "Please set the `FIREWORKS_API_KEY` environment variable in your Space settings."
101
  return
102
 
 
103
  messages = [{"role": "system", "content": SYSTEM_PROMPT}]
104
  for entry in history:
105
  messages.append({"role": entry["role"], "content": entry["content"]})
106
  messages.append({"role": "user", "content": message})
107
 
108
  try:
109
+ resp = fireworks_chat(messages, stream=True)
110
+ resp.raise_for_status()
 
 
 
 
 
111
  partial = ""
112
+ for line in resp.iter_lines(decode_unicode=True):
113
+ if not line or not line.startswith("data: "):
114
+ continue
115
+ data = line[6:]
116
+ if data.strip() == "[DONE]":
117
+ break
118
+ chunk = json.loads(data)
119
+ delta = chunk.get("choices", [{}])[0].get("delta", {}).get("content", "")
120
  if delta:
121
  partial += delta
122
  yield partial
 
194
  file, question: str, history: list[dict]
195
  ) -> tuple[list[dict], str, str | None, str]:
196
  """Main analysis pipeline: upload data, ask question, get results."""
197
+ if not FIREWORKS_API_KEY:
198
+ msg = "Please set the `FIREWORKS_API_KEY` environment variable."
199
  return history + [{"role": "assistant", "content": msg}], "", None, ""
200
 
201
  df, summary_md = load_data(file)
 
229
  question=question,
230
  )
231
 
 
232
  messages = [{"role": "system", "content": SYSTEM_PROMPT}]
233
  for entry in history:
234
  messages.append({"role": entry["role"], "content": entry["content"]})
235
  messages.append({"role": "user", "content": prompt})
236
 
237
  try:
238
+ resp = fireworks_chat(messages, stream=False)
239
+ resp.raise_for_status()
240
+ result = resp.json()
241
+ answer = result["choices"][0]["message"]["content"] or ""
 
 
242
  except Exception as e:
243
  answer = f"API Error: {e}"
244
  return (
 
393
 
394
  | Variable | Description |
395
  |----------|-------------|
396
+ | `FIREWORKS_API_KEY` | Your Fireworks AI API key |
397
+ | `FIREWORKS_MODEL` | Model name (default: accounts/fireworks/models/kimi-k2p5) |
 
398
 
399
  ### Links
400
  - [GitHub Repository](https://github.com/NousResearch/hermes-agent)
requirements.txt CHANGED
@@ -1,5 +1,5 @@
1
  gradio>=5.0,<6
2
- openai>=2.21.0,<3
3
  pandas>=2.0,<3
4
  matplotlib>=3.7,<4
5
  plotly>=5.18,<6
 
1
  gradio>=5.0,<6
2
+ requests>=2.31,<3
3
  pandas>=2.0,<3
4
  matplotlib>=3.7,<4
5
  plotly>=5.18,<6