feat(ultraplan-local): v1.6.0 — /ultraresearch-local deep research command

Add /ultraresearch-local for structured research combining local codebase
analysis with external knowledge via parallel agent swarms. Produces research
briefs with triangulation, confidence ratings, and source quality assessment.

New command: /ultraresearch-local with modes --quick, --local, --external, --fg.
New agents: research-orchestrator (opus), docs-researcher, community-researcher,
security-researcher, contrarian-researcher, gemini-bridge (all sonnet).
New template: research-brief-template.md.

Integration: --research flag in /ultraplan-local accepts pre-built research
briefs (up to 3), enriches the interview and exploration phases. Planning
orchestrator cross-references brief findings during synthesis.

Design principle: Context Engineering — right information to right agent at
right time. Research briefs are structured artifacts in the pipeline:
ultraresearch → brief → ultraplan --research → plan → ultraexecute.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-04-08 08:58:35 +02:00
commit baa2d0220b
488 changed files with 213221 additions and 0 deletions

View file

@ -0,0 +1,586 @@
# Token Counting and Optimization Strategies
**Last updated:** 2026-02
**Status:** GA
**Category:** Cost Optimization & FinOps for AI
---
## Introduksjon
Token counting og optimization er fundamentale teknikker for å kontrollere kostnader i Azure OpenAI og andre LLM-baserte løsninger. Siden fakturering baserer seg på antall tokens (både input og output), er presis måling og aktiv reduksjon av token-forbruk kritisk for økonomisk bærekraft — spesielt i høyvolum-scenarier.
**Hovedpoeng:**
- Tokens er basisenheten for prosessering — typisk ~4 tegn per token i engelsk tekst
- Kostnader påløper for både input-tokens (prompt) og output-tokens (completion)
- Ulike modeller har ulik pris per 1M tokens (typisk $2-100 USD / 1M tokens avhengig av modell)
- Prompt caching, context management og compression kan redusere kostnader med 50-90%
**Confidence:** High (basert på offisiell Microsoft-dokumentasjon)
---
## Kjernekomponenter
### Token Counting Tools
| Verktøy | Språk | Bruksområde | Nøyaktighet |
|---------|-------|-------------|-------------|
| **tiktoken** | Python, JS | OpenAI-modeller (GPT-4o, o1, o3, etc.) | Eksakt for støttede modeller |
| **Microsoft.ML.Tokenizers** | .NET/C# | Cross-model tokenisering, BPE, Tiktoken | Eksakt |
| **Hugging Face Tokenizers** | Python, JS, Java | Åpen-modell-tokenisering | Varierer per modell |
### tiktoken — Azure OpenAI Standard
```python
import tiktoken
# Encoding for GPT-4o og nyere modeller
encoding = tiktoken.get_encoding("o200k_base") # Default for gpt-4o, o1, o3
tokens = encoding.encode("Tell me about Azure AI")
token_count = len(tokens)
# Model-spesifikk encoding
try:
encoding = tiktoken.encoding_for_model("gpt-4o")
except KeyError:
encoding = tiktoken.get_encoding("o200k_base")
```
**Message Overhead Calculation:**
```python
def num_tokens_from_messages(messages, model="gpt-4o"):
"""Return the number of tokens used by a list of messages."""
try:
encoding = tiktoken.encoding_for_model(model)
except KeyError:
encoding = tiktoken.get_encoding("o200k_base")
if model in {"gpt-4o", "gpt-4o-mini", "gpt-5", "gpt-4.1", "o1", "o3", "o4-mini"}:
tokens_per_message = 3
tokens_per_name = 1
num_tokens = 0
for message in messages:
num_tokens += tokens_per_message
for key, value in message.items():
num_tokens += len(encoding.encode(value))
if key == "name":
num_tokens += tokens_per_name
num_tokens += 3 # every reply is primed with <|start|>assistant<|message|>
return num_tokens
```
### Microsoft.ML.Tokenizers (.NET)
```csharp
using Microsoft.ML.Tokenizers;
// Installer pakker:
// dotnet add package Microsoft.ML.Tokenizers
// dotnet add package Microsoft.ML.Tokenizers.Data.O200kBase
var tokenizer = Tokenizer.CreateTiktokenForModel("gpt-4o");
var tokens = tokenizer.CountTokens("Tell me about Azure AI");
// Trimming til token-limit
string TrimToTokenLimit(string text, int maxTokens, Tokenizer tokenizer)
{
var ids = tokenizer.Encode(text).Ids;
if (ids.Count <= maxTokens)
return text;
var trimmedIds = ids.Take(maxTokens).ToArray();
return tokenizer.Decode(trimmedIds);
}
```
### Token Usage Estimation (Azure OpenAI On Your Data)
```python
import tiktoken
class TokenEstimator(object):
GPT2_TOKENIZER = tiktoken.get_encoding("gpt2")
def estimate_tokens(self, text: str) -> int:
return len(self.GPT2_TOKENIZER.encode(text))
token_output = TokenEstimator().estimate_tokens(input_text)
```
**Merk:** On Your Data RAG har kompleks token-fordeling:
- **20% av context window** reservert for model response
- **80%** deles mellom meta prompt, spørsmål, conversation history og retrieved chunks
- User question og history: capped ved 2 000 tokens
- Retrieved documents: varierer basert på chunk size og antall retrieved chunks
---
## Arkitekturmønstre
### 1. Prompt Caching (Native Azure OpenAI)
**Automatisk aktivert for GPT-4o og nyere modeller**
| Parameter | Verdi | Effekt |
|-----------|-------|--------|
| Minimum prompt length | 1 024 tokens | Cache hit kan først oppnås |
| Granularitet | 128 tokens | Etter første 1024 tokens, cache hit per 128 tokens |
| Cache TTL | 24 timer | Azure AI Foundry Classic |
| Cache TTL | 5-10 min idle, max 1 time | Azure AI Services |
| Kostnad (Standard) | 50% rabatt på cached tokens | Varierer per modell |
| Kostnad (Provisioned) | Opptil 100% rabatt | Inkludert i PTU-pris |
**Design-prinsipper:**
1. **Plasser repetitivt innhold først** — system messages, instructions, reference docs
2. **Bruk `prompt_cache_key`** for å påvirke routing og øke cache hit rate
3. **Unngå variasjon i første 1024 tokens** — én endring = cache miss
```python
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "Long system prompt..."}, # Cached
{"role": "user", "content": "Variable user question"}
],
extra_body={"prompt_cache_key": "my-app-v1"} # Optional routing hint
)
# Response inkluderer:
# usage.prompt_tokens_details.cached_tokens
```
**Kostnad-eksempel:**
- 10 000 requests/dag med 2 000 tokens prompt
- Uten caching: 10 000 × 2 000 = 20M input tokens/dag
- Med 90% cache hit: 10 000 × 200 + (10 000 × 1 800 × 0.5) = 11M "effective" tokens
- **Besparelse: 45% på input-kostnader**
### 2. Conversation History Management
**Problem:** Chat-applikasjoner akkumulerer context over tid → økte token costs
**Løsning:** Dynamisk trimming med preservation av system message
```python
system_message = {"role": "system", "content": "You are a helpful assistant."}
max_response_tokens = 250
token_limit = 4096
conversation = [system_message]
def manage_conversation_tokens(conversation, max_response_tokens, token_limit):
while True:
user_input = input("Q: ")
conversation.append({"role": "user", "content": user_input})
conv_tokens = num_tokens_from_messages(conversation, model="gpt-4o")
# Trim oldest messages (preserve system message)
while conv_tokens + max_response_tokens >= token_limit:
del conversation[1] # Remove oldest non-system message
conv_tokens = num_tokens_from_messages(conversation, model="gpt-4o")
response = client.chat.completions.create(
model="gpt-4o",
messages=conversation,
max_tokens=max_response_tokens
)
conversation.append({
"role": "assistant",
"content": response.choices[0].message.content
})
```
**Alternative strategier:**
- **Sliding window:** Behold kun N siste turns
- **Summarization:** Compress old history til summary
- **Session reset:** Start ny conversation ved token limit
- **Responses API:** La Azure OpenAI håndtere truncation automatisk
### 3. Space-Efficient Formatting
**Token-ineffektive formater:**
```json
{"date": "January 15, 2026"} // 7 tokens
{"date": "01/15/2026"} // 9 tokens (!)
```
**Token-effektive formater:**
```
January 15, 2026 // 5 tokens
2026-01-15 // 5 tokens
| Name | Age | Role | // Tabular > JSON
| Alice | 30 | Dev |
```
**Whitespace-regler:**
- Konsekutive whitespace = separate tokens (waste)
- Leading space on word = typisk samme token
- Bruk tabeller over verbose JSON når mulig
### 4. Max Prompt/Completion Tokens (Assistants API)
```python
run = client.beta.threads.runs.create(
thread_id=thread.id,
assistant_id=assistant.id,
max_prompt_tokens=20000, # Limit context usage
max_completion_tokens=1000, # Limit output
truncation_strategy={
"type": "last_messages",
"last_messages": 10
}
)
```
**Anbefalinger:**
- **File Search:** Min. 20 000 prompt tokens, ideelt 50 000+
- **Langvarige samtaler:** Fjern `max_prompt_tokens` limit for best quality
- **Cost-sensitive apps:** Set strict limits + handle `incomplete` status
### 5. Chunking for Embeddings & RAG
**Token-limit per chunk:**
- `text-embedding-ada-002`: 8 191 tokens
- `text-embedding-3-small/large`: 8 191 tokens
```python
from langchain.text_splitter import RecursiveCharacterTextSplitter
import tiktoken
tokenizer = tiktoken.get_encoding('cl100k_base')
def tiktoken_len(text):
tokens = tokenizer.encode(text, disallowed_special=())
return len(tokens)
# Analyze document token distribution
token_counts = [tiktoken_len(page.page_content) for page in pages]
print(f"Min: {min(token_counts)}, Avg: {sum(token_counts)/len(token_counts)}, Max: {max(token_counts)}")
# Create chunks with overlap
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000, # Target tokens
chunk_overlap=200, # Overlap for context
length_function=tiktoken_len
)
chunks = text_splitter.split_documents(pages)
```
### 6. Fine-Tuning Token Accounting
**Training cost formula (SFT/DPO):**
```
Cost = # training tokens × # epochs × price per token
```
**Token validation pre-training:**
```python
import json
import tiktoken
import numpy as np
encoding = tiktoken.get_encoding("o200k_base")
def num_tokens_from_messages(messages, tokens_per_message=3, tokens_per_name=1):
num_tokens = 0
for message in messages:
num_tokens += tokens_per_message
for key, value in message.items():
num_tokens += len(encoding.encode(value))
if key == "name":
num_tokens += tokens_per_name
num_tokens += 3
return num_tokens
# Validate training file
with open('training_set.jsonl', 'r', encoding='utf-8') as f:
dataset = [json.loads(line) for line in f]
total_tokens = [num_tokens_from_messages(ex["messages"]) for ex in dataset]
print(f"Mean: {np.mean(total_tokens)}, Median: {np.median(total_tokens)}")
print(f"p5 / p95: {np.quantile(total_tokens, 0.05)}, {np.quantile(total_tokens, 0.95)}")
```
**Token limits:**
- `gpt-4o-mini`: Training example max 64 536 tokens, input limit 128 000 tokens
- Overfør lange eksempler = feil ved training
- Kostnad: $2 per 1M training tokens (gpt-4.1 global, eksempel)
---
## Beslutningsveiledning
### Når skal du prioritere token optimization?
| Scenario | Anbefalt Tiltak | Forventet Besparelse |
|----------|-----------------|----------------------|
| **Høyvolum chatbot** (>10K requests/dag) | Prompt caching + conversation trimming | 40-60% input cost |
| **RAG-applikasjon** | Chunk size optimization + reranking | 30-50% total cost |
| **Long-context prompts** (>8K tokens) | Prompt caching + structured outputs | 50-90% input cost |
| **Multi-turn conversations** | Sliding window + summarization | 20-40% total cost |
| **Batch processing** | Global Standard deployment + compression | 10-30% total cost |
| **Fine-tuning** | Dataset pruning + epoch optimization | 30-60% training cost |
### Decision Tree: Optimization Strategy
```
Er prompt >1024 tokens og repetitiv?
├─ Ja → Implementer prompt caching (automatisk på GPT-4o+)
│ └─ Strukturer prompt med statisk innhold først
└─ Nei → Er det multi-turn conversation?
├─ Ja → Implementer conversation history trimming
│ └─ Sliding window eller summarization
└─ Nei → Er det RAG?
├─ Ja → Optimaliser chunk size + reranking
│ └─ Bruk strictness parameter
└─ Nei → Er output verbose/unstructured?
├─ Ja → Bruk structured outputs (JSON schema)
└─ Nei → Bruk space-efficient formatting (tabeller)
```
### Monitoring & Alerting
**Key metrics:**
- `prompt_tokens` / `completion_tokens` per request
- `cached_tokens` (prompt_tokens_details) — cache hit rate
- Cost per 1K tokens (varierer per model + deployment type)
- Total daily/monthly token consumption
**Azure Cost Management:**
- Filtrer på "Meter" for å se input/output tokens separat
- Filtrer på deployment tags for model-spesifikk cost
- Sett opp budgets med alerts (90% / 100% thresholds)
---
## Integrasjon med Microsoft-stakken
### Azure OpenAI Service
| Deployment Type | Input Token Pricing | Cached Token Discount | Output Token Pricing |
|----------------|---------------------|----------------------|---------------------|
| **Standard (Regional)** | $2.50-$100 per 1M | 50% rabatt | $10-$300 per 1M |
| **Global Standard** | 10-30% lavere | 50% rabatt | 10-30% lavere |
| **Provisioned (PTU)** | Inkludert i PTU | Opptil 100% rabatt | Inkludert i PTU |
**Merk:** Priser varierer betydelig per modell (gpt-4o vs. o1 vs. gpt-4.1)
### Azure AI Foundry
**Token Usage Estimation (On Your Data):**
- Intent prompt: ~1 366 tokens (gjennomsnitt)
- Generation prompt: ~4 297 tokens (gjennomsnitt)
- Response: ~111 tokens (gjennomsnitt)
- Intent output: ~25 tokens (gjennomsnitt)
- **Total per request:** ~5 800 tokens
**Cost monitoring:**
1. Foundry portal → Operate → Overview → Estimated cost tile
2. Build → Models → Monitor tab → Token costs
3. Azure portal → Cost Management → Group by Meter
### Copilot Studio
- **Token-basert billing** for Generative Answers (Azure OpenAI)
- **Message-basert billing** for standard topics
- Token counting via `AI Builder credits` — prompt tokens + image/doc conversions
**Image token conversion:**
- Low-res (<512×512): 85 tokens flat
- High-res: Resize to 2048×2048, split into 512×512 tiles, 170 tokens per tile + 85 base
### Power Platform (AI Builder)
```
Token cost = Prompt tokens + completion tokens + image tokens
Image tokens (high-res) = (# tiles × 170) + 85
```
**Optimization:**
- Resize images før submission for å redusere tiles
- Bruk "low detail" setting når mulig
- Cache prompts i Power Automate flows
---
## Offentlig sektor (Norge)
### Compliance & Data Residency
**Token counting = metadata, ikke innhold:**
- Token-tellingen selv er ikke persondata
- Loggføring av token counts er OK for kostnadsoppfølging
- **Unngå:** Logging av faktisk prompt content uten GDPR-vurdering
**Anbefalt praksis:**
- Aggreger token metrics (daglig/ukentlig totals)
- Logg kun token counts, ikke text content
- Bruk Azure Monitor for telemetri (data residency i Norge)
### Kostnadsfordeling (Intern Fakturering)
**Tagging-strategi:**
```json
{
"tags": {
"cost_center": "IT-seksjonen",
"project": "Saksbehandling-AI",
"environment": "prod"
}
}
```
**Azure Cost Management:**
- Filtrer på tags for per-avdeling/prosjekt cost
- Eksporter cost data til Excel/Power BI for intern rapportering
- Bruk budgets med action groups for automatisk varsling
### Transparent kostnadsstyring
**Eksempel: Fylkeskommunal saksbehandling**
- Estimert 500 saker/dag × 10 000 tokens/sak = 5M tokens/dag
- Med prompt caching: 2.5M "effective" tokens/dag
- Kostnad (gpt-4o-mini, $0.15/$0.60 per 1M): ~$1/dag input + $3/dag output = **~$120/måned**
**Budsjettjustering:**
- Start med conservative estimates (worst case = no caching)
- Monitor faktisk forbruk over 1-2 måneder
- Juster deployment type (Standard vs. Provisioned) basert på volum
---
## Kostnad og lisensiering
### Azure OpenAI Pricing (Eksempler, februar 2026)
| Modell | Input (per 1M tokens) | Cached Input | Output (per 1M tokens) | Context Window |
|--------|-----------------------|--------------|------------------------|----------------|
| **gpt-4o** | $2.50 | $1.25 | $10.00 | 128K |
| **gpt-4o-mini** | $0.15 | $0.075 | $0.60 | 128K |
| **o1** | $15.00 | $7.50 | $60.00 | 200K |
| **o3-mini** | $1.10 | $0.55 | $4.40 | 200K |
| **gpt-4.1** | $2.00 | $1.00 | $8.00 | 128K |
**Merk:** Priser er illustrative. Sjekk alltid [offisiell pricing page](https://azure.microsoft.com/pricing/details/cognitive-services/openai-service/).
### Fine-Tuning Costs
**Training (SFT/DPO):**
- Global Standard: $2 per 1M tokens (gpt-4.1, eksempel)
- Developer (spot): 50% rabatt, kan bli paused/resumed
**Hosting:**
- $1.70/time per deployment (Standard/Global Standard)
- Påløper selv om modellen ikke brukes
- **VIKTIG:** Slett ubrukte deployments for å unngå "idle hosting cost"
**Inference:**
- Samme per-token pris som base model + hosting fee
- Developer tier: Ingen hosting fee, men deployment auto-deletes etter 24 timer
### Provisioned Throughput (PTU)
- **Flat månedlig kostnad** basert på antall PTUs
- Input/output tokens inkludert (ingen per-token cost)
- Prompt caching: Opptil 100% rabatt (effektivt "gratis" cached tokens)
- **Break-even:** Typisk ~50M tokens/måned (varierer per modell)
---
## For arkitekten (Cosmo)
### Når anbefale token optimization?
**Always recommend:**
- Prompt caching for repetitive prompts (>1024 tokens)
- Conversation history management for chatbots
- Token monitoring/budgets for alle produksjonsmiljøer
**Situational recommend:**
- **High-volume (>1M requests/måned):** Aggressive optimization (chunking, compression, structured outputs)
- **Low-volume (<100K requests/måned):** Basic optimization (caching, trimming), fokus på function over cost
- **Fine-tuning:** Dataset pruning + epoch optimization alltid (training cost accumulates fast)
### Spørsmål å stille kunden
1. **Volum:** Forventet antall requests per dag/måned?
2. **Prompt-lengde:** Gjennomsnittlig antall tokens i prompts?
3. **Repetisjon:** Hvor mye av prompten er statisk vs. dynamisk?
4. **Conversation length:** Multi-turn (chat) eller single-shot (completion)?
5. **Response length:** Trengs lange svar, eller kan det begrenses?
6. **Budsjett:** Er det hard cap på månedlige AI-kostnader?
### Implementation Checklist
- [ ] Implementer tiktoken/Microsoft.ML.Tokenizers for telemetri
- [ ] Strukturer prompts med static content først (for caching)
- [ ] Sett opp Azure Cost Management budgets + alerts
- [ ] Implementer conversation trimming (hvis multi-turn)
- [ ] Logg `cached_tokens` metric for cache hit rate monitoring
- [ ] Vurder Provisioned deployment hvis >50M tokens/måned
- [ ] Dokumenter token-fordeling i ADR (Architecture Decision Record)
### Fallgruver å unngå
| Fallgruve | Konsekvens | Løsning |
|-----------|------------|---------|
| **Ingen token monitoring** | Ukontrollerte kostnader | Sett opp Cost Management alerts ASAP |
| **Ubrukte fine-tuned deployments** | $1.70/time hosting × 24 × 30 = $1 224/måned idle | Auto-delete etter N dager uten bruk |
| **Variasjon i første 1024 tokens** | Cache miss = full input cost | Flytt dynamic content til slutten av prompt |
| **Over-chunking i RAG** | Mange små chunks = mange embeddings calls | Optimaliser chunk size (500-1500 tokens sweet spot) |
| **Manglende output limits** | Ukontrollerte completion tokens | Sett `max_tokens` parameter |
### Code Snippet: Production Token Telemetry
```python
import tiktoken
from azure.monitor.opentelemetry import configure_azure_monitor
from opentelemetry import metrics
# Configure Azure Monitor
configure_azure_monitor(connection_string="InstrumentationKey=...")
meter = metrics.get_meter(__name__)
token_counter = meter.create_counter("aoai.tokens", description="Token usage")
cost_counter = meter.create_counter("aoai.cost_usd", description="Estimated cost")
encoding = tiktoken.get_encoding("o200k_base")
def track_token_usage(prompt, completion, model="gpt-4o"):
prompt_tokens = len(encoding.encode(prompt))
completion_tokens = len(encoding.encode(completion))
# Log to Azure Monitor
token_counter.add(prompt_tokens, {"type": "input", "model": model})
token_counter.add(completion_tokens, {"type": "output", "model": model})
# Estimate cost (example rates)
input_cost = (prompt_tokens / 1_000_000) * 2.50
output_cost = (completion_tokens / 1_000_000) * 10.00
cost_counter.add(input_cost + output_cost, {"model": model})
```
---
## Kilder og verifisering
**Microsoft Learn Documentation:**
1. [Prompt caching - Azure OpenAI](https://learn.microsoft.com/en-us/azure/ai-foundry/openai/how-to/prompt-caching)
2. [Work with chat completions models - Token management](https://learn.microsoft.com/en-us/azure/ai-foundry/openai/how-to/chatgpt#manage-conversations)
3. [Plan and manage costs for Azure OpenAI](https://learn.microsoft.com/en-us/azure/ai-foundry/openai/how-to/manage-costs)
4. [Token counting in AI - Dynamics 365 Business Central](https://learn.microsoft.com/en-us/dynamics365/business-central/dev-itpro/developer/ai-system-app-token-counting)
5. [Use Microsoft.ML.Tokenizers for text tokenization](https://learn.microsoft.com/en-us/dotnet/ai/how-to/use-tokenizers)
6. [Azure OpenAI On Your Data - Token usage estimation](https://learn.microsoft.com/en-us/azure/ai-foundry/openai/concepts/use-your-data#token-usage-estimation-for-azure-openai-on-your-data)
7. [Cost management for fine-tuning](https://learn.microsoft.com/en-us/azure/ai-foundry/openai/how-to/fine-tuning-cost-management)
**OpenAI Resources:**
8. [OpenAI Cookbook - Token counting](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb)
9. [tiktoken GitHub repository](https://github.com/openai/tiktoken)
**Verification Date:** 2026-02-04
**MCP Calls:** 4 (microsoft_docs_search × 3, microsoft_docs_fetch × 2, microsoft_code_sample_search × 1)
**Confidence Level:** High — all data sourced from official Microsoft Learn documentation and verified OpenAI tooling