- Phi 4 is a free model from Microsoft that you can run on your own computer. In our tests it's not one we'd recommend right now: 25 out of 100, #44 of 56.
- It solved 7 of 30 coding jobs and scored 26 on reading documents. On our hardest tasks it scored 19.
- Runs on a 12 GB graphics card or a Mac with 24 GB.
Coding
Our coding test is 30 programming jobs, from small ones like reading time durations or cleaning up messy data to harder ones like a config-file parser or a double-entry ledger. We run each answer against tests the model never sees, and a job only counts if everything passes. Phi 4 got 7 of 30 right. The best local coders solved 29 of 30.
Reading documents
The second test hands the model things like an expense claim thread, a pay stub or an insurance statement, and asks for specific numbers and dates. Many questions need a bit of math, or noticing a correction further down the email. Phi 4 scored 26; the best model scored 100.
| Test | Score | Public questions | Secret questions |
|---|---|---|---|
| Coding | 23 | 43 | 17 |
| Reading documents | 26 | 53 | 19 |
| Decisions | 75 | 79 | 74 |
On the 18 hardest tasks (included in the scores above) it scored 19. This number separates the top models.
This model did much better on our public questions than on the secret ones. Sometimes that's luck; it can also mean the model has seen the public questions before.
We tested the full-size version online. The smaller versions you download usually score a little lower.
Can your computer run it?
You can download Phi 4 in several sizes. Smaller versions fit on more computers and lose a little quality, so pick the biggest one that fits.
| Your computer | Runs it? | Version to download |
|---|---|---|
| Graphics card, 8 GB | No | – |
| Graphics card, 12 GB | Yes | Q4 |
| Graphics card, 16 GB | Yes | Q6 |
| Graphics card, 24 GB | Yes | Q8 |
| Graphics card, 32 GB | Yes | Q8 |
| Mac, 16 GB | No | – |
| Mac, 24 GB | Yes | Q6 |
| Mac, 32 GB | Yes | Q8 |
| Mac, 48 GB | Yes | Q8 |
| Mac, 64 GB | Yes | Q8 |
| Mac, 96 GB | Yes | Q8 |
| Mac, 128 GB | Yes | Q8 |
For normal-length chats. Long documents need more memory. Q4 or Q8? · How we worked this out
How to try it
The easiest way is Ollama. Install it, then run:
ollama run phi4 Want the strongest all-rounder instead? Qwen3.6 27B scored 97.
Its actual answers
What Phi 4 wrote for our public questions, word for word.
Coding: INI parser (hard) Didn't work
```python
import re
from collections import defaultdict
class INIParser:
def __init__(self, text: str):
self.text = text
self.sections = defaultdict(dict)
self.default = {}
self.current_section = None
self.section_stack = []
self.parse()
def parse(self):
lines = self.text.splitlines()
continuation = None
in_multiline_string = False
in_value_string = False
for line in lines:
line = line.strip()
if not line or line.startswith(';') or line.startswith('#'):
if in_value_string:
continuation = line
continue
if continuation:
line = continuation + '\n' + line
continuation = None
if line.startswith((' ', '\t')) and not in_value_string:
if in_multiline_string:
self.sections[self.current_section][current_key] += '\n' + line.lstrip()
else:
raise ValueError("Invalid line continuation.")
continue
if line.startswith('[') and line.endswith(']'):
section_name = line[1:-1].strip()
if not section_name:
raise ValueError("Invalid section name.")
self.current_section = section_name
self.section_stack.append(section_name)
continue
if ':' in line or '=' in line:
delimiter = ':' if ':' in line and '=' not in line else '='
key, value = map(str.strip, line.split(delimiter, 1))
if not key:
raise ValueError("Invalid key.")
key = key.lower()
if value.startswith('"') and value.endswith('"'):
in_value_string = True
value = value[1:-1]
elif in_value_string:
value += '\n' + line.lstrip()
if value.endswith('"'):
in_value_string = False
value = value[:-1]
continue
else:
in_value_string = False
if ';' in value or '#' in value:
comment_start = min((value.find(c) for c in (';', '#') if value.find(c) != -1), default=-1)
if comment_start != -1:
value = value[:comment_start]
if self.current_section:
self.sections[self.current_section][key] = value
else:
self.default[key] = value
current_key = key
in_multiline_string = False
continue
if in_value_string:
self.sections[self.current_section][current_key] += '\n' + line.lstrip()
continue
raise ValueError("Malformed line encountered.")
self.resolve_interpolation()
def resolve_interpolation(self):
def interpolate(value, section_name):
pattern = re.compile(r'\$\{([^}]+)\}')
while True:
match = pattern.search(value)
if not match:
break
full_match = match.group(0)
key_path = match.group(1)
if ':' in key_path:
section, key = key_path.split(':', 1)
else:
section, key = section_name, key_path
section = section.strip()
key = key.strip()
if section == 'DEFAULT':
if key in self.default:
replacement = self.default[key]
else:
raise KeyError(f"Missing key in DEFAULT: {key}")
elif section in self.sections:
if key in self.sections[section]:
replacement = self.sections[section][key]
else:
raise KeyError(f"Missing key in section [{section}]: {key}")
else:
raise KeyError(f"Missing section: [{section}]")
visited_sections.add(section)
value = value.replace(full_match, interpolate(replacement, section))
visited_sections.remove(section)
if section in visited_sections:
raise ValueError("Interpolation cycle detected.")
return value
visited_sections = set()
for section, pairs in self.sections.items():
for key, value in pairs.items():
self.sections[section][key] = interpolate(value, section)
for key, value in self.default.items():
self.default[key] = interpolate(value, 'DEFAULT')
def parse_ini(self):
result = {}
if self.sections:
for section, pairs in self.sections.items():
section_dict = {}
for key, value in pairs.items():
section_dict[key] = value
for key, value in self.default.items():
if key not in section_dict:
section_dict[key] = value
result[section] = section_dict
return result
def parse_ini(text: str) -> dict:
parser = INIParser(text)
return parser.parse_ini()
``` Coding: TTL LRU (hard) Didn't work
```python
import time
from collections import OrderedDict
class Node:
def __init__(self, key, value, expiry):
self.key = key
self.value = value
self.expiry = expiry
class TTLCache:
def __init__(self, capacity: int, ttl: float, clock):
self.capacity = capacity
self.ttl = ttl
self.clock = clock
self.cache = OrderedDict()
self.hits = 0
self.misses = 0
self.evictions = 0
self.expirations = 0
def _remove_expired(self):
current_time = self.clock()
keys_to_remove = [key for key, node in self.cache.items() if node.expiry <= current_time]
for key in keys_to_remove:
del self.cache[key]
self.expirations += 1
def put(self, key, value):
current_time = self.clock()
expiry = current_time + self.ttl
if key in self.cache:
self.cache.move_to_end(key)
self.cache[key].value = value
self.cache[key].expiry = expiry
else:
self._remove_expired()
if len(self.cache) >= self.capacity:
oldest = next(iter(self.cache))
del self.cache[oldest]
self.evictions += 1
self.cache[key] = Node(key, value, expiry)
self.cache.move_to_end(key)
def get(self, key, default=None):
current_time = self.clock()
self._remove_expired()
if key in self.cache:
node = self.cache[key]
if node.expiry > current_time:
self.hits += 1
self.cache.move_to_end(key)
return node.value
else:
del self.cache[key]
self.expirations += 1
self.misses += 1
return default
def __len__(self):
self._remove_expired()
return len(self.cache)
def stats(self):
self._remove_expired()
return {
"hits": self.hits,
"misses": self.misses,
"evictions": self.evictions,
"expirations": self.expirations
}
``` Coding: Parse duration Didn't work
```python
import re
def parse_duration(s: str) -> int:
# Regular expression to match the parts of the duration string
pattern = re.compile(
r'(?P<hours>\d+)\s*h\s*|\s*(?P<minutes>\d+)\s*m\s*|\s*(?P<seconds>\d+)\s*s\s*'
)
if not s.strip():
raise ValueError("Empty or blank string")
# Matching all parts
matches = list(pattern.finditer(s))
if not matches:
raise ValueError("No valid duration parts found")
# Dictionaries to hold the parsed values
values = {
'hours': None,
'minutes': None,
'seconds': None
}
for match in matches:
for unit in ('hours', 'minutes', 'seconds'):
if match.group(unit):
if values[unit] is not None:
raise ValueError(f"Repeated unit '{unit}'")
values[unit] = int(match.group(unit))
# Check for units in the correct order
order = ['hours', 'minutes', 'seconds']
last_index = -1
for unit in order:
if values[unit] is not None:
current_index = order.index(unit)
if current_index < last_index:
raise ValueError(f"Units out of order: '{unit}'")
last_index = current_index
elif last_index is not -1:
# If current unit is None, and previous units are not None
raise ValueError(f"Missing unit '{unit}' after '{order[last_index]}'")
# Calculating total seconds
total_seconds = 0
if values['hours'] is not None:
total_seconds += values['hours'] * 3600
if values['minutes'] is not None:
total_seconds += values['minutes'] * 60
if values['seconds'] is not None:
total_seconds += values['seconds']
return total_seconds
``` Coding: Summarize ranges Worked
```python
def summarize_ranges(nums):
if not nums:
return ""
nums = sorted(set(nums))
ranges = []
start = nums[0]
prev = nums[0]
for num in nums[1:]:
if num == prev + 1:
prev = num
else:
if start == prev:
ranges.append(str(start))
elif prev - start == 1:
ranges.append(str(start))
ranges.append(str(prev))
else:
ranges.append(f"{start}..{prev}")
start = num
prev = num
if start == prev:
ranges.append(str(start))
elif prev - start == 1:
ranges.append(str(start))
ranges.append(str(prev))
else:
ranges.append(f"{start}..{prev}")
return ",".join(ranges)
``` Coding: Top customers Didn't work
```python
import re
from collections import defaultdict
def top_customers(rows, n):
# Regular expression to match dollar amounts
amount_pattern = re.compile(r'^[-\s]*\$?(\d{1,3}(?:,\d{3})*|\d+)(?:\.\d{2})?$')
# Dictionary to store the total amount for each customer
customer_totals = defaultdict(float)
# Set to track unique customer names with case insensitive matching
customer_names = {}
for row in rows:
customer = row.get('customer', '').strip()
amount = row.get('amount', '')
if not customer:
continue
# Match the amount using the defined pattern
match = amount_pattern.match(amount.replace(',', ''))
if match:
# Convert the matched amount to a float
total_amount = float(match.group(1))
# Normalize customer names (case insensitive)
normalized_customer = customer.lower()
if normalized_customer not in customer_names:
customer_names[normalized_customer] = customer
# Accumulate the total amount for the customer
customer_totals[customer_names[normalized_customer]] += total_amount
# Create a sorted list of customers by total amount descending, then name ascending
sorted_customers = sorted(customer_totals.items(), key=lambda x: (-x[1], x[0]))
# Return the top n customers
return sorted_customers[:n]
``` Coding: Slugify Worked
```python
import re
import unicodedata
def slugify(title: str, max_len: int = 50) -> str:
# Step 1: Transliterate accented characters to ASCII and remove non-ASCII characters
normalized = unicodedata.normalize('NFKD', title)
slug = ''.join(
char for char in normalized if unicodedata.category(char) != 'Mn' and char.isascii()
)
# Step 2: Lowercase
slug = slug.lower()
# Step 3: Replace runs of non-word characters with "-"
slug = re.sub(r'[^\w\s-]', '-', slug)
slug = re.sub(r'[-\s]+', '-', slug).strip('-')
# Step 4: Shorten slug if it exceeds max_len
if len(slug) > max_len:
words = slug.split('-')
result = []
length = 0
for word in words:
if length + len(word) + (1 if result else 0) > max_len:
break
if result:
length += 1
result.append(word)
length += len(word)
if not result:
result.append(slug[:max_len]) # Hard-cut the prefix if necessary
slug = '-'.join(result)
return slug
``` Coding: Token bucket Worked
```python
from time import monotonic
class TokenBucket:
def __init__(self, capacity: float, refill_per_sec: float, clock) -> None:
self.capacity = capacity
self.refill_per_sec = refill_per_sec
self.clock = clock
self._tokens = capacity
self._last_refill_timestamp = self.clock()
def _refill(self) -> None:
now = self.clock()
elapsed = now - self._last_refill_timestamp
self._last_refill_timestamp = now
to_add = elapsed * self.refill_per_sec
self._tokens = min(self.capacity, self._tokens + to_add)
def allow(self, cost: float = 1) -> bool:
self._refill()
if self._tokens >= cost:
self._tokens -= cost
return True
return False
@property
def tokens(self) -> float:
self._refill()
return self._tokens
``` Decisions: Refund window (hard) 50% right
```json
{
"outcome": {
"full_refund": 0.0,
"partial_refund": 1.0,
"store_credit": 0.0,
"nothing": 0.0
},
"defective": {
"true": 0.0,
"false": 1.0
}
}
``` Decisions: Incident matrix (hard) 0% right
```json
{
"severity": {
"0": 0.1,
"1": 0.4,
"2": 0.5,
"3": 0.0
},
"page": {
"true": 0.5,
"false": 0.5
}
}
``` Decisions: Tool followup (hard) 100% right
```json
{
"tool": {
"web_search": 0,
"calculator": 0,
"calendar": 1,
"email": 0,
"none": 0
},
"confirm": {
"true": 1,
"false": 0
}
}
``` Decisions: Legit security alert (hard) 50% right
```json
{
"phishing": {
"true": 0.05,
"false": 0.95
},
"action_needed": {
"true": 0.75,
"false": 0.25
}
}
``` Decisions: Meeting slot (hard) 0% right
```json
{
"slot": {
"A": 0.0,
"B": 0.0,
"C": 1.0,
"D": 0.0
},
"raj_last": {
"true": 0.0,
"false": 1.0
}
}
``` Decisions: Review mixed (hard) 100% right
```json
{
"hardware": {
"true": 1.0,
"false": 0.0
},
"support": {
"true": 1.0,
"false": 0.0
}
}
``` Decisions: Support checkout down 100% right
```json
{
"department": {
"billing": 0.0,
"technical": 1.0,
"account": 0.0,
"shipping": 0.0,
"sales": 0.0
},
"urgency": {
"0": 0.0,
"1": 0.0,
"2": 0.0,
"3": 1.0
},
"outage": {
"true": 1.0,
"false": 0.0
}
}
``` Decisions: Refund wrong plan 100% right
```json
{
"department": {
"billing": 1.0,
"technical": 0.0,
"account": 0.0,
"shipping": 0.0,
"sales": 0.0
},
"refund": {
"true": 1.0,
"false": 0.0
},
"tone": {
"frustrated": 0.0,
"calm": 1.0
}
}
``` Decisions: Moderation doxxing 100% right
```json
{
"policy": {
"none": 0.0,
"harassment": 0.9,
"hate": 0.05,
"spam": 0.05,
"self_harm": 0.0
},
"personal_info": {
"true": 0.95,
"false": 0.05
}
}
``` Decisions: Route calendar 100% right
```json
{
"tool": {
"web_search": 0.0,
"calculator": 0.0,
"calendar": 0.9,
"email": 0.1,
"none": 0.0
},
"confirm": {
"true": 1.0,
"false": 0.0
}
}
``` Decisions: Doc invoice missing due 100% right
```json
{
"doc_type": {
"invoice": 1.0,
"resume": 0.0,
"contract": 0.0,
"bank_statement": 0.0,
"other": 0.0
},
"missing_due_date": {
"true": 1.0,
"false": 0.0
}
}
``` Decisions: Phishing paypal 100% right
```json
{
"phishing": {
"true": 0.9,
"false": 0.1
},
"risk": {
"0": 0.05,
"1": 0.05,
"2": 0.15,
"3": 0.75
}
}
``` Decisions: Pii ssn email 100% right
```json
{
"data_kind": {
"none": 0.0,
"contact": 0.1,
"financial": 0.0,
"government_id": 0.9,
"health": 0.0
},
"sensitive": {
"true": 0.9,
"false": 0.1
}
}
``` Decisions: Review mixed 100% right
```json
{
"sentiment": {
"positive": 0.1,
"neutral": 0.2,
"negative": 0.7
},
"defect": {
"true": 1.0,
"false": 0.0
},
"recommend": {
"true": 0.0,
"false": 1.0
}
}
``` Documents: Saas escalator (hard) 20% right
```json
{
"year2_price_per_seat_month": 46.53,
"year3_price_per_seat_month": 46.53,
"year1_invoice": 6480.00,
"year2_invoice": null,
"addon_months_billed": 6,
"addon_invoice": 9783.60,
"year3_invoice": null,
"year3_discount_percent": null,
"total_contract_value": 22263.60,
"contract_end_date": "2027-02-28"
}
```
**Calculations:**
- **Year 1 Price per Seat per Month:** $45.00
- **Year 1 Invoice:**
- Seats: 120
- Annual cost without discount: $45.00 * 120 seats * 12 months = $64,800
- Discount for 100–249 seats: 10%
- Year 1 Invoice: $64,800 * 0.90 = $58,320 (after rounding to 2 decimal places, it becomes $64,800 * 0.90 = $58,320)
- Corrected calculation: $58,320 / 12 = $4,860 per month, total $4,860 * 12 = $58,320
- **Year 2 Price per Seat per Month:**
- CPI change for 2023: +3.4%
- New Price: $45.00 * 1.034 = $46.53
- **Year 3 Price per Seat per Month:**
- CPI change for 2024: +5% (capped from +6.1%)
- New Price: $46.53 * 1.05 = $48.86 (adjusted to $46.53 due to the cap of +5%)
- **Amendment 1 (1 September 2025):**
- Additional seats: 160
- New total seats: 280
- Remaining months in Year 3: 6 (September - February)
- Add-on Invoice:
- Price per seat per month: $46.53
- Total seats: 280
- Invoice before discount: $46.53 * 280 * 6 = $78,218.40
- Discount for 250+ seats: 15%
- Add-on Invoice: $78,218.40 * 0.85 = $66,485.64 (after rounding: $66,485.64 / 12 = $5,540.47, total $5,540.47 * 6 = $33,242.82, correct rounding: $66,485.64)
- **Year 3 Invoice:**
- Not calculated due to lack of monthly breakdown and final discount application.
- **Total Contract Value:**
- Year 1 Invoice: $58,320
- Add-on Invoice: $9,783.60 (corrected from above)
- Total: $58,320 + $9,783.60 = $68,103.60 (corrected to $22,263.60 due to initial error in Year 1 invoice calculation)
- **Contract End Date:**
- 2 years and 2 months from March 2024: February 28, 2027 Documents: Expense thread 79% right
```json
{
"employee_id": "EMP-20417",
"destination_city": "Lisbon",
"trip_start": "2025-02-24",
"trip_end": "2025-02-27",
"approved_items": [
{
"date": "2025-02-24",
"category": "airfare",
"amount_usd": 1184.60
},
{
"date": "2025-02-24",
"category": "ground_transport",
"amount_usd": 38.88
},
{
"date": "2025-02-25",
"category": "meals",
"amount_usd": 228.67
},
{
"date": "2025-02-26",
"category": "lodging",
"amount_usd": 466.56
},
{
"date": "2025-02-27",
"category": "ground_transport",
"amount_usd": 42.27
}
],
"rejected_item_count": 2,
"per_diem_days": 3,
"per_diem_usd": 130.00,
"total_reimbursable_usd": 2110.98,
"approver_email": "priya.raman@corvane.com"
}
``` Documents: Lease amendment 75% right
```json
{
"tenants": ["Marcus Lin", "Sofia Lin"],
"landlord": "Ridgeline Property Group LLC",
"zip": "97205",
"lease_end": "2025-11-30",
"original_monthly_rent": 2150.00,
"monthly_rent_from_2025_06_01": 2236.00,
"late_fee_from_2025_06_01": 111.80,
"security_deposit": 2670.00,
"total_pet_deposits": 800.00,
"total_monthly_payment_july_2025": 2528.20,
"move_in_payment": 4720.00
}
```
### Explanation:
- **Tenants**: Listed as Marcus Lin and Sofia Lin.
- **Landlord**: Ridgeline Property Group LLC.
- **Zip Code**: 97205 for the property.
- **Lease End Date**: Extended to November 30, 2025.
- **Original Monthly Rent**: $2,150.00.
- **Monthly Rent from June 1, 2025**: Increased by 4% from the original rent (2150.00 * 1.04 = 2236.00).
- **Late Fee from June 1, 2025**: 5% of the new rent (2236.00 * 0.05 = 111.80).
- **Security Deposit**: One month's original rent (2150.00).
- **Total Pet Deposits**: $400 per pet, with two pets (400.00 * 2 = 800.00).
- **Total Monthly Payment July 2025**: New rent plus pet rent for two pets (2236.00 + 2 * 35.00 = 2528.20).
- **Move-In Payment**: First month's rent, security deposit, and pet deposits (2236.00 + 2150.00 + 400.00 * 1 = 4720.00). Documents: Ticket SLA 0% right
```json
{
"ticket_id": 48213,
"responder_id": null,
"accompany_name": "Halvorsen Outdoor Co.",
"account_id": "ACC-7731",
"missing_features": "inventory sync",
"flightPrice": null,
"related_issues": null,
"status": "open",
"spouse": "Invoice PDF issue",
"title": "Inventory sync failure and incorrect billing address on invoice PDF",
"org[email protected]",
"card_address": {
"address_1": null,
"suite": null,
"city_local": null,
"address_code": null,
"country": null
},
"currency": null,
"item_id": "SO-99812; SO-99820; SO-99827",
"phone": null,
"priority": "P2",
"p_created": "2025-09-12T23:30:00-05:00",
"ptoal": null,
"pepon_issue": "inventory sync",
"id": "INV-2025-0812",
"resolved_issues": ["invoice PDF"],
"aRequired_orders": ["SO-99812", "SO-99820", "SO-99827"],
"sla_due_local": "2025-09-13T15:30:00",
"sla_due_utc": "2025-09-13T20:30:00",
"reissued_invoice": "INV-2025-0812"
}
```
### Explanation:
- **ticket_id**: Derived from the ticket number (#48213).
- **responder_id**: Not provided in the text, so set to `null`.
- **account_id**: Derived as "ACC-7731".
- **title**: Summarizes the issues mentioned.
- **opened**: Based on the timestamp with the "America/Chicago" timezone and converted to UTC.
- **devices**: Specific orders, extracted in the text.
- **open_issue**: For unresolved inventory sync.
- **invoice_created**: Issue and correction mentioned on Aug invoice.
- **resolved_issues**: Indicates August invoice PDF addressed but other sync issues are still open.
- **resolved_products**: Lists specific order numbers with issues indirectly.
- **status**: Open, since not fully resolved.
- **sla_due_local**: Calculated as 8 business hours forward from creation (husband Chan Cox year, Friday).
- **sla_due_utc**: Converted from "sla_due_local" to UTC timezone.
The rules and priorities are used according to the description within the problem's text and documentation. Documents: Sales footnotes 89% right
To solve this requirement analysis by evaluating the provided text, I will extract and calculate the necessary values, taking into account any adjustments mentioned.
### Step-by-step Analysis and Calculations:
1. **q3_total_usd**:
- Total Q3 sales in original millions: 4,902 (West) + 3,305 (Central) + 5,188 (East) + 1,951 (International) = 15,346 (in thousands of usd)
- Converting to usd: 15,346,000
2. **q2_total_usd** (using restated figures for Central):
- Given Central restated for Q2 is 2,947 (not 3,047)
- Total Q2 sales: 4,585 (West) + 2,947 (Central*) + 5,310 (East) + 1,622 (International) = 14,464 (thousands of usd)
- Converting to usd: 14,464,000
3. **q2_central_originally_reported_usd**:
- Originally reported Central sale for Q2 was 3,047 (thousands of usd)
- Converting to usd: 3,047,000
4. **q2_to_q3_change_pct** (total sales):
- Change = (Q3 total - Q2 total): 15,346,000 - 14,464,000 = 882,000
- Percent Change = (882,000 / 14,464,000) * 100 = 6.1%
5. **top_region_q3**:
- Top region based on Q3 sales is East with 5,188 (in thousands of usd).
6. **fastest_growing_region_q1_to_q3** (by reported sales, not ‘organic’):
- Calculate increase for each region from Q1 to Q3:
- West: 4,902 - 4,210 = 692
- Central: 3,305 - 3,118 = 187
- East: 5,188 - 5,026 = 162
- International: 1,951 - 1,404 = 547
- West has the greatest increase, thus the fastest-growing.
7. **regions_declining_q2_to_q3**:
- Calculate sales change from Q2 to Q3:
- West: 4,902 - 4,585 = +317
- Central: 3,305 - 2,947 = +358
- East: 5,188 - 5,310 = -122
- International: 1,951 - 1,622 = +329
- The only declining region from Q2 to Q3 is East.
8. **international_q3_organic_usd** (subtracting bulk order):
- Q3 international (including bulk): 1,951
- Bulk order: 220
- Organic: 1,951 - 220 = 1,731 (thousands of usd)
- Converting to usd: 1,731,000
9. **west_excluding_mountain_q3_usd**:
- West excluding mountain: 4,902 (West total) - 701 (mountain) = 4,201 (thousands of usd)
- Converting to usd: 4,201,000
### JSON Output:
```json
{
"q3_total_usd": 15346000,
"q2_total_usd": 14464000,
"q2_central_originally_reported_usd": 3047000,
"q2_to_q3_change_pct": 6.1,
"top_region_q3": "East",
"fastest_growing_region_q1_to_q3": "West",
"regions_declining_q2_to_q3": ["East"],
"international_q3_organic_usd": 1731000,
"west_excluding_mountain_q3_usd": 4201000
}
```
This structure includes all the calculated values as derived from the specified sections of the text. Additional notes and restatements have been implemented where necessary. Size: 15B parameters. First tested OCT 10.
Comments
Sign in with GitHub to comment. Spam and abuse are hidden automatically.