AI 资讯
Building an Enterprise Football Data Pipeline: Decoding Flashscore's Protocol for xG & Referee Analytics
Most football data scrapers on the market only extract high-level final scores (e.g. 2-1 ). But quantitative sports analysts, data scientists, and predictive betting modelers need granular data: Expected Goals (xG) , Official Referee Assignments , Goal Scorers paired with Assist Providers , and Half-Time vs Full-Time (1H/2H) statistical breakdowns . When I set out to build a professional-grade Flashscore scraper on Apify, I ran into two major engineering challenges: The Memory Problem : Keeping Puppeteer running to scrape hundreds of historical matches consumes over 1.5GB of RAM per run. The Protocol Problem : Flashscore serves its deep statistical feeds using a proprietary pipe-delimited data format ( ~ , ¬ , ÷ ) over CDN endpoints, rather than standard REST APIs. In this tutorial, I'll explain how I engineered the Flashscore Elite Statistics Extractor , how the hybrid Browser + HTTP/2 streaming pipeline drops RAM footprint from 1.5GB to 70MB , how to parse Flashscore's custom feed protocol, and how to pipe the resulting datasets directly into Python and Pandas. 🏛️ The Hybrid Pipeline Architecture To achieve zero proxy reliance for standard runs and ultra-low compute costs, the Actor splits execution into a 2-Phase Hybrid Pipeline : [ League & Season Selection ] │ ▼ ┌───────────────────────────────────────────┐ │ Phase 1: Browser Handshake (Puppeteer) │ │ - Captures x-fsign security tokens │ │ - Extracts countryId & tourId │ └─────────────────────┬─────────────────────┘ │ [ Immediate Browser Shutdown ] (RAM drops from 1.2GB -> 70MB) │ ▼ ┌───────────────────────────────────────────┐ │ Phase 2: Parallel HTTP/2 Feed Workers │ │ - got-scraping with JA3 TLS matching │ │ - Decodes df_st_1_ (Stats) & df_sui_1_ │ └─────────────────────┬─────────────────────┘ │ ▼ ┌───────────────────────────────────────────┐ │ Self-Healing Recovery Pass │ │ - Auto-retries skipped/failed matches │ └─────────────────────┬─────────────────────┘ │ ▼ ┌───────────────────────────────────────────┐
AI 资讯
Chinese LLM API Pricing Comparison 2026: The Definitive Buyer's Guide
If you're shopping for LLM APIs in 2026, Chinese vendors are impossible to ignore. As of August 21, 2026 (always check official pricing pages for the final word), flagship Chinese models charge between ¥4.00 and ¥12.00 per million input tokens — with ERNIE 5.1 at ¥4.00, GLM-5.1 at ¥6.00, Kimi K2.6 at ¥6.50, DeepSeek V4 Pro at ¥9.00, and Qwen3.7 Max at ¥12.00. Budget-tier input can be as low as ¥0.20 (Qwen3.5 Flash), and value models like DeepSeek V4 are 80–98% cheaper than GPT-5.5-class peers. But don't pick a model on sticker price alone. Cache hit rates, endpoint access, and tool-calling fit often matter more than nominal list prices. The data below was verified against official pricing pages by llmabacus on 2026-08-21. Chinese vendors have turned quarterly price cuts into a structural competitive weapon: DeepSeek V4 Flash, for example, offers cached input at ¥0.10 per million tokens — just 1/30th of its standard input price. 2026 Chinese LLM API Pricing Landscape: An Overview The 2026 Chinese LLM market is shaped by three forces: Hardware cost deflation — cheaper compute keeps pushing prices down. Escalating domestic price wars — vendors undercut each other every quarter. Aggregator endpoints — services that arbitrage price gaps and unify access. As of Aug 2026, tracking firm pricepertoken lists 610+ models globally, 43 of them free. Paid input prices range from roughly $0 to $150 per million tokens. Chinese vendors sit in the lowest price band, and many update prices quarterly — as Morph noted in its 2026-06-28 analysis: "LLM prices change every quarter." Final prices are subject to each vendor's official pricing page: DeepSeek Alibaba Cloud Bailian/Qwen Moonshot/Kimi Zhipu GLM Baidu ERNIE Tencent Hunyuan The main camps remain unchanged: DeepSeek and Alibaba's Qwen dominate the extreme value tier. Kimi (Moonshot) differentiates on ultra-long context. GLM (Zhipu) , Doubao , and Tencent Hunyuan serve the domestic enterprise market. OpenAI , Claude , and Gemini hol
AI 资讯
Polymarket TWAP60 vs Kalshi: Why Settlement Design Decides Your Bot (Series 1/4)
GitHub: https://github.com/abrownfox0/abrownfox001-twap60-prediction-trigger-system YouTube walkthrough: https://www.youtube.com/watch?v=XzhugRL6BV4 This is a new 4-part series comparing the two venues that actually matter for short-horizon BTC direction: Part 1 — Settlement design: Polymarket TWAP60 vs Kalshi 60s average (this post) Part 2 — Product shape: 5-minute specialist vs 15-minute regulated stack Part 3 — What a directional bot must change when crossing venues Part 4 — Where edge survives, and where it dies Live profile: @abrownfox001 The Real Split Is Not “On-Chain vs Regulated” People compare Polymarket and Kalshi as if the important difference is KYC, geography, or chain vs centralized matching. For a short-horizon BTC bot, those matter later. The first difference is simpler: What exact number decides Up vs Down? If you get that wrong, every signal, backtest, and scratch rule is solving the wrong problem. Two Venues, Two Official Averages Both platforms moved away from “whatever the last print was.” Both now settle short BTC contracts on a one-minute average . They do not use the same average. Polymarket crypto Up/Down Kalshi BTC short contracts Shortest liquid product 5-minute Up/Down 15-minute Up/Down ( KXBTC15M ) Settlement idea Time-weighted average 60-second simple average Official source Chainlink TWAP CF Benchmarks Real-Time Index (BRTI family) Window 60 seconds for current 5m / 15m / 4h crypto Final 60 seconds before close , sampled ~1s Open reference Matching TWAP at slot start Strike / floor set by the contract Feed path for bots Polymarket RTDS or Chainlink Data Streams Kalshi market fields + CF Benchmarks index Market structure On-chain CLOB Centralized CFTC-regulated exchange Same word — “60-second average.” Different index. Different sampling. Different product clock. Why Both Platforms Converged on 60 Seconds Snapshot settlement created the same failure mode everywhere: A brief push into one venue’s book A wick at the exact close Retail on
AI 资讯
Implementing SMS Delivery Status Polling for Restaurant Waitlist Outage Alerts
Short answer: Choose an SMS API for critical outage alerts only if your backend can poll delivery status and own retry, escalation, cancellation, and timing logic; for restaurant waitlist updates, treat the provider as a delivery transport rather than as the incident workflow itself. The deciding constraint is delivery reliability. Sending a message is the easy part; deciding whether an unresolved alert should be polled again, resent, escalated through another channel, or canceled after recovery is where the application earns its reliability. An API that can send, expose status and events, resend, and cancel covers those transport mechanics. Without webhook pushes, however, the backend must run polling frequently enough for its actual alert deadline. This is a conditional yes, not a blanket recommendation. Timing dominates. How should you choose an SMS API for critical outage alerts? Start with an explicit service-level objective for the restaurant workflow. A waitlist delay notice might tolerate a polling interval that a critical app outage alert cannot. Write down the maximum time from initial send to the next decision, the point at which another attempt becomes stale, and the moment when recovery must suppress queued or repeat messages. If those values are missing, comparing provider feature lists produces a confident-looking choice with no reliability argument behind it. Four invariants matter here. Every accepted send needs an application-owned identifier; every retry must be bounded and idempotent; every delivery state must lead to a defined next action; and incident recovery must stop obsolete alerts. SMS cancel support helps with the last invariant, but cancellation is not permission to ignore timing: the application still has to notice recovery and issue the decision promptly. There is a hard boundary. No webhook event push means that delivery updates arrive only when the application asks for them, so a ten-second polling job cannot support a five-second es
AI 资讯
I built an open-source directory of 50+ free public APIs with daily automated health-checks
Hey everyone! 👋 Finding reliable, free public APIs for side projects or learning is always a hassle because many listed APIs eventually go down or become paid. To solve this, I created Awesome Free APIs Live — an open-source, curated collection of 50+ free public APIs across AI, developer tools, security, and open data. ⚙️ How It Works Daily Health Checks: Powered by GitHub Actions , an automated script tests endpoints daily and updates live status badges. Zero Dead Links: Broken endpoints are flagged automatically so developers don't waste time debugging dead services. Categorized & Searchable: Clean, categorized UI hosted on GitHub Pages. ### 🔗 Links 🌐 Live Directory: shilpshakti.github.io/awesome-free-apis-live ⭐ GitHub Repository: github.com/ShilpShakti/awesome-free-apis-live Contributions are very welcome! If you know of any great free APIs, feel free to open a PR or check out the open issues on GitHub.
AI 资讯
Webhooks vs Polling: Why Real-Time Integrations Matter in 2026
Webhooks vs Polling: Why Real-Time Integrations Matter in 2026 In modern software, knowing that something happened is often just as important as knowing what happened. A customer completes a payment. An order changes from pending to shipped. A user creates an account. A GitHub pull request is opened. A subscription is renewed. An AI workflow needs to start processing a new request. The question is simple: How does your application know that something changed? For years, developers have relied on two common approaches: polling and webhooks. Both solve the same fundamental problem—keeping systems synchronized—but they do it in completely different ways. Polling repeatedly asks an API whether something has changed. Webhooks allow the external system to notify your application when something actually happens. That difference can have a major impact on performance, scalability, API usage, responsiveness, reliability, and overall system architecture. And as applications become increasingly connected in 2026, understanding when to use each approach is more important than ever. What Is Polling? Polling is the traditional approach to checking for changes. Your application periodically sends a request to another system: “Has anything changed?” For example, imagine an e-commerce application that needs to know when an order has been paid. It might call an API every 30 seconds: GET /orders/12345 The response might say: status: pending Thirty seconds later, the application asks again. Then again. And again. Eventually: status: paid The application finally discovers that the payment has been completed. The basic workflow looks like this: Application → API → “Anything new?” API → Application → “No.” Thirty seconds later: Application → API → “Anything new?” API → Application → “No.” Eventually: Application → API → “Anything new?” API → Application → “Yes, the order has been paid.” The approach is straightforward and easy to understand. But there is a problem. Most of those requests
AI 资讯
A Self-Correcting Solar System Baseline From Sunrise/Sunset Data
A fixed-schedule solar baseline drifts out of sync with the sun throughout the year. In Phoenix the sun is up for 13 hours 10 minutes in late August and 10 hours 2 minutes at the December solstice. A flat daily kWh target flags that entire winter as a fault, then stays quiet on the July afternoon when one string dies at 2pm under full sun. The fix is to anchor the baseline to the actual sun instead of the clock, and most of what you need for that does not require an irradiance forecast. One thing before any code: sun geometry tells you when a system should be producing and when it should peak. It does not tell you how much light actually reached the panels. That is irradiance, and cloud cover swamps it. If you want modeled output in kWh, reach for Forecast.Solar or Solcast, which fold in weather and your array's tilt and azimuth. What follows is the free, dependency-light layer underneath that: the daylight window, the solar-noon peak, and the day-length trend. TL;DR Sun geometry (sunrise, sunset, solar noon, day length) catches a specific class of solar underperformance with no irradiance data. Gate alerts to the real daylight window so your monitor stops crying "underperformance" before sunrise. Track the daily production peak relative to solar noon. A persistent shift across comparable days can reveal shading, orientation, or system changes that a total-kWh check misses. Normalize a flat kWh target by day length so winter stops tripping false alarms. First-order fix, not a physics model. One call to an astronomy endpoint returns all of it. Code below in curl, Python, and Node. For real production forecasting, use an irradiance API. Sun times are the sanity layer, not the forecaster. Sun times will not predict your kWh, but they eliminate common timing-based false alarms and can surface useful production-shape anomalies early. Pull sunrise, sunset, solar noon, and day length once a day, gate your alerts to daylight, watch the peak, and scale the target for season.
AI 资讯
Build a caption QA harness in Python: WER, missed entities, timing and reading rate
TL;DR We're building a caption evaluation harness that scores a WebVTT file on four axes instead of one: word error rate under a fixed normalizer, missed entity rate on domain terms, median cue timing offset, and reading rate in characters per second. Python 3.12, jiwer , whisper_normalizer , webvtt-py . Run it on every model or vendor change. A caption file can score 96% accurate and still be unusable. WER counts substitutions, insertions and deletions and weighs each one the same, so "fifteen milligrams" becoming "fifty milligrams" costs exactly as much as "the" becoming "a". It also throws away every timestamp before it starts, which means synchronization and readability are invisible to it. Let's measure the other three things. 0. Setup 🛠️ python3 -m venv .venv && source .venv/bin/activate pip install jiwer whisper_normalizer webvtt-py $ pip list | grep -Ei 'jiwer|whisper|webvtt' jiwer <your version> webvtt-py <your version> whisper-normalizer <your version> Pin whatever you install, and pin it in CI. The APIs below move between majors, which is exactly why the next tip exists. 💡 Tip: jiwer.compute_measures() is gone in recent versions. It is jiwer.process_words() now, and it returns a WordOutput dataclass. Most blog posts you will find still use the old name. 1. Parse the VTT into text plus timings # captions.py from dataclasses import dataclass import webvtt @dataclass class Cue : start : float end : float text : str @property def duration ( self ) -> float : return self . end - self . start @property def lines ( self ) -> list [ str ]: return self . text . split ( " \n " ) @property def flat ( self ) -> str : return " " . join ( l . strip () for l in self . lines ) @property def chars_per_second ( self ) -> float : return len ( self . flat ) / self . duration if self . duration > 0 else float ( " inf " ) def _to_seconds ( ts : str ) -> float : h , m , s = ts . split ( " : " ) return int ( h ) * 3600 + int ( m ) * 60 + float ( s ) def load_vtt ( path : str ) -
AI 资讯
I Built a GTM Research Workflow with One Vaaya API Key
I wanted to see how far I could take a simple idea: Give an agent one API key and let it handle the different pieces of company research. So I built GTM Radar . You paste a company URL, and it turns that into a structured GTM brief instead of making you jump between different research and data tools. What GTM Radar does The workflow currently generates five main sections: Overview — company description, industry, size, location and website Structure — departments and key people Market — signals, competitors and positioning People — who might be relevant to reach and why Outreach — why now and a possible angle The goal is simple: go from company URL → useful GTM context as quickly as possible. Why Vaaya? The interesting part for me was being able to connect several providers through Vaaya rather than integrating each one separately. The workflow currently uses: Firecrawl · Exa · Akta · OpenFunnel · OneFind through a single Vaaya key. Vaaya's API provides a common interface for its catalog, so the workflow can call different services using the same API authentication and request pattern. It also supports cost limits and only charges successful calls. That made experimenting with different providers much easier. The workflow At a high level: Company URL ↓ Company discovery / extraction ↓ Company + market research ↓ People & GTM signals ↓ Structured GTM brief ↓ Share / copy / reuse The interesting part isn't any individual API call. It's combining several data sources into something that is actually useful to a person doing GTM research. Handling failures Real-world data workflows don't always return clean results. For extraction, I added a fallback path so that if the first provider doesn't work, the workflow can try another route instead of immediately failing. The current flow is roughly: CRW ↓ Firecrawl scrape ↓ CRW fallback I also added cost-capped runs and a 12-hour cache to avoid unnecessary repeated work. Sharing the research The latest thing I added was Share I
AI 资讯
A Practical Pattern for Giving AI Agents Access to External APIs with MCP
Connecting an AI agent to one API is straightforward. Connecting it to many changing APIs—without filling the model context with hundreds of tool definitions—is a different problem. Disclosure: This article was prepared for QVeris and uses QVeris as the implementation example. This tutorial presents a practical pattern for developers building agents that need current external data: discover → inspect → probe → call . Instead of exposing every possible operation up front, the agent discovers the capabilities relevant to the current task, verifies the selected tool, validates its inputs, and only then executes it. TL;DR: Keep the agent's initial tool surface small. Let it discover a capability by intent, inspect the exact schema, probe the request without execution, and make a real call only after the parameters and expected cost are understood. Contents Why a large static tool list becomes difficult The four-step capability workflow Connecting a hosted MCP server A concrete example Production checklist Why a large static tool list becomes difficult An agent connected directly to several providers may need to understand different authentication schemes, parameter conventions, response formats, and error behaviors. Loading every operation into context can also make tool selection less reliable. Model Context Protocol (MCP) provides a standard way for clients to connect to tools and data sources. The protocol solves the connection boundary, but developers still need a strategy for controlling how many capabilities the model sees and when execution is allowed. A compact routing layer is useful when: the agent needs data from multiple API providers; the appropriate provider depends on the user's request; schemas or available operations may change; calls can consume credits or trigger rate limits; you want to validate inputs before executing a paid operation. The four-step capability workflow 1. Discover The agent starts with a natural-language description of the capabilit
AI 资讯
The agent posted successfully. To the wrong account.
Back in July I wrote about what it takes to wire an AI agent into social platforms: six OAuth flows,...
AI 资讯
Stop rewriting your API responses in Laravel (Use this Trait instead)
If you are building API-driven applications, nothing clutters up your controllers faster than manually typing out response()->json(...) arrays every single time you need to return data or throw an error. When you have inconsistent response structures, your frontend (and the developers consuming your API) will constantly have to guess whether the data is nested under ['data'] , ['payload'] , or just at the root of the object. The cleanest way I've found to standardize this across an entire application is by creating a dedicated ApiResponse trait. Instead of rewriting your JSON structure in every controller method, create this trait in your app/Traits directory: namespace App\Traits ; use Illuminate\Http\JsonResponse ; trait ApiResponse { protected function success ( mixed $data , ?string $message = null , int $code = 200 ): JsonResponse { return response () -> json ([ 'status' => 'success' , 'message' => $message , 'data' => $data ], $code ); } protected function error ( string $message , int $code = 400 , array | string $errors = []): JsonResponse { // Force errors into an array format for consistent frontend parsing $formattedErrors = is_string ( $errors ) ? [ $errors ] : $errors ; return response () -> json ([ 'status' => 'error' , 'message' => $message , 'errors' => $formattedErrors ], $code ); } } Next, simply use this trait inside your base Controller.php . Now, your actual endpoints become incredibly readable and strictly standardized: namespace App\Http\Controllers ; use App\Models\Task ; use Illuminate\Http\Request ; use Illuminate\Http\JsonResponse ; use Throwable ; class TaskController extends Controller { public function store ( Request $request ): JsonResponse { $validated = $request -> validate ([ 'title' => 'required|string|max:255' , 'description' => 'nullable|string' ]); try { $task = Task :: create ( $validated ); return $this -> success ( $task , 'Task successfully generated' , 201 ); } catch ( Throwable $e ) { // Note: Exposing raw exception messa
AI 资讯
From Termux to a Freestyle VM: My Osintgram and HikerAPI Experiment
From Termux to a Freestyle VM: My Osintgram and HikerAPI Experiment After experimenting with Osintgram directly in Termux, I wanted to see how the same project behaved inside a Linux environment running through a Freestyle VM. The idea was not simply to reproduce the installation. I wanted to understand whether moving the project into the VM would make the HikerAPI troubleshooting any clearer. Why use a VM? Termux is capable of running many command-line tools directly on Android, but a VM provides a more conventional Linux environment. I connected to the Freestyle VM from Termux and worked with Osintgram from there. The project could start, but the API side still required investigation. The dependency confusion One of the first things I noticed was that there were multiple API-related components involved. I initially looked at the installed "hikerapi" package and its "Client" class. That alone wasn't enough to explain what Osintgram was doing. So I switched from inspecting only the Python environment to inspecting the project's source code. The HikerAPI-related code pointed me toward: src/hikercli.py This was much more informative because it showed where the client was being configured and how the access token entered the application. Checking the installed library I also checked the installed HikerAPI package rather than assuming I had the expected version. For example: python3 -m pip show hikerapi This let me verify the package that was actually installed in the VM. The important point here is that checking a package version and understanding how the application uses that package are two different troubleshooting steps. Separating authentication from Osintgram I found it useful to test the API independently instead of using Osintgram as the only diagnostic tool. For example: import requests headers = { "x-access-key": "YOUR_KEY" } r = requests.get( " https://api.hikerapi.com/v2/user/by/username?username=natgeo ", headers=headers ) print(r.json()) Again, "YOUR_KEY"
AI 资讯
I Reviewed 12 Free-Tier Integrations. The Same Six Myths Kept Appearing.
I Reviewed 12 Free-Tier Integrations. The Same Six Myths Kept Appearing. Last month I reviewed twelve integrations that used free model servers. All twelve carried the same wrong assumptions. None of them tested those assumptions. That's the real problem. Not the free tier. The mental model. How many of these myths do you believe? I believed all of them. Here's what the code told me. Disclosure: This article was prepared as part of MonkeyCode's product outreach. I use their free server option in side projects. The probe below works with any OpenAI-compatible endpoint, including theirs. The Six Myths Myth 1: "Free tier is just a demo" Teams treat free servers like toy boxes. They build demos, then throw them away. Evidence: three of the twelve integrations were internal tools in daily use. The free tier was the production environment. Nobody planned for that. Corrected mental model: free tier is a constraint, not a demo. If the tool survives, the constraint becomes your architecture. Design for it from day one. Myth 2: "A 200 means it worked" The most dangerous assumption. A 200 only means the HTTP layer succeeded. It says nothing about the content. I found empty completions, truncated JSON, and repeated boilerplate. All returned 200. All broke the caller. Corrected mental model: validate the payload, not the status code. Check schema, length, and content markers. Myth 3: "Retries are free" When a request fails, developers retry immediately. Then again. Then again. That's a retry storm. It amplifies load exactly when the server struggles. I saw one integration fire eleven requests in four seconds. Corrected mental model: retries are a queue, not a hammer. Use exponential backoff with jitter. Add a circuit breaker. Myth 4: "The model is the same everywhere" Free and paid tiers often serve different models. Or the same name with different behavior. You cannot assume. Evidence: two integrations hard-coded model names that no longer existed. Responses came back, but from
开发者
Day 7 & 8: Python Full Stack Development
Day 7 & 8 of learning Python Full Stack Development, yesterday and today I have started taking an notes for my project ideas and studying about API. As I'm going to started my project, reading some SRS, architecture and features involving in my project and side by side I was learning fastAPI
AI 资讯
Runable hits $21M to bet AI agents can go from building businesses to growing them
Runable says 60%–70% of its 1 trillion-plus token usage in the last 90 days came from paying customers.
AI 资讯
Testing an AI shopping agent's checkout flow? There's no sandbox for that yet — so I built one
If you're building or evaluating an AI agent that can shop and check out on its own, you've probably run into the new "agentic commerce" protocols: ACP (OpenAI + Stripe + Meta), AP2 (Google), and UCP. They define how an agent talks to a merchant to create a checkout session, apply a payment token, and get an order back. Stripe's own test mode covers the payment half fine — test cards, test API keys. But there's no hosted "fake merchant" you can point your agent at to verify the protocol half: does your agent correctly create a session, handle a 422 idempotency conflict, parse the order response, retry politely? You either mock it yourself from the spec, or risk finding out against a real merchant. So I built acp-sandbox — a small hosted mock merchant implementing the ACP checkout API, live at https://acp-sandbox.flo-voice1.com . What it does It implements the real checkout_sessions lifecycle from ACP's 2026-04-17 spec : create, retrieve, update, complete, cancel. Responses match the actual CheckoutSession / Order / Error schemas for the fields it supports — I pulled the OpenAPI spec directly rather than guessing field names. # get a test key, no signup curl -X POST https://acp-sandbox.flo-voice1.com/keys \ -H "Content-Type: application/json" -d '{"email":"you@example.com"}' # create a session against the demo catalog curl -X POST https://acp-sandbox.flo-voice1.com/checkout_sessions \ -H "Authorization: Bearer acps_test_..." \ -H "Content-Type: application/json" \ -d '{"line_items":[{"id":"item_demo_headphones","quantity":1}],"currency":"usd"}' Every request/response is logged per API key ( GET /logs ), so you can see exactly what your agent sent when something doesn't work. What it deliberately doesn't do (yet) No real payment processing — complete always succeeds once you send any payment_data . No OAuth delegate_authentication flow. No fulfillment options (shipping/pickup) — every session goes straight to ready_for_payment . Fixed demo catalog (4 items), not a rea
AI 资讯
How to Build an Agentic RAG Pipeline with Real-Time Web Search
TL;DR An agentic RAG pipeline treats retrieval as a tool the AI agent can call, evaluate, and call again rather than as a fixed step. The pipeline can search an internal knowledge base first, then use real-time web search when the available evidence is missing, weak, or outdated. Internal documents and web results should be converted into a shared evidence format before the model generates an answer. A reliable system must preserve URLs, publication dates, document identifiers, and the claims supported by each source. Retrieval quality, web-search precision, citation correctness, latency, cost, and stopping behaviour should all be evaluated. A basic RAG pipeline works well until the answer is not in the knowledge base. Imagine an enterprise copilot that can answer questions about internal product documentation. It performs semantic search against a vector database, retrieves several relevant passages, and passes them to a language model. For questions covered by the indexed documents, the system may work remarkably well. Then a user asks about a release announced yesterday, a recently changed regulation, or how the company’s product compares with a new competitor. The vector database cannot retrieve information it has never indexed. A conventional pipeline may return no answer, but it may also produce a confident response from incomplete or outdated context. Adding a Web Search API helps solve the freshness problem, but it introduces another decision: when should the system trust its internal knowledge, and when should it search the open web? An agentic RAG pipeline places that decision inside the retrieval workflow. What Makes a RAG Pipeline Agentic? A traditional RAG pipeline usually follows a fixed path: transform the question into a search query, retrieve the most similar passages, add those passages to the prompt, and generate an answer. An agentic RAG pipeline allows the model to make decisions between those stages. Retrieval becomes a tool rather than a manda
AI 资讯
Keenable: Agent-First Search API Architecture and the 100B-Page Index Trade-Off
Agents don't search like humans. They issue hundreds of queries per session, need structured extraction over snippet relevance, and care more about p95 latency than the perfect top result. Keenable built a search API around those constraints with a 100B+ page proprietary index, SQL-like query interface, and continuous benchmarking against agent-like workloads. The founders (Amazon AGI web grounding, Yandex search lead) are betting that wrapping existing search APIs won't cut it when agents become the primary consumers of web data. The architecture reveals what changes when you optimize for machine callers instead of human eyeballs. Why Agent Search Needs Different Plumbing Human search optimizes for the first three results and tolerates 500ms variance. Agent search runs in tight loops where every query blocks downstream tool calls. The contract shifts: Query volume : Agents issue 10-100x more queries per task than humans per session Latency budget : p95 matters because agents serialize tool calls; tail latency compounds across multi-step workflows Result consumption : Agents parse structured data, not blue links; relevance scoring for human click-through doesn't align with extraction success Query patterns : Agents use precise filters (date ranges, domain constraints, schema hints) that humans rarely specify Traditional search APIs built for human traffic handle agent workloads poorly. Rate limits assume sporadic queries. Pricing tiers penalize high-volume programmatic access. Relevance models optimize for engagement metrics that don't exist in agent contexts. The 100B-Page Index Decision Keenable maintains its own crawl and index instead of wrapping Google, Bing, or Brave. This is expensive but unlocks control over: Crawl strategy : Agents need fresh data on niche domains that human-centric crawlers deprioritize. A proprietary crawl can target high-churn sources (job boards, pricing pages, event listings) and re-crawl on agent-driven schedules rather than PageRank-
AI 资讯
Adding OpenAPI Support to Mummy, a Nim HTTP Framework
Nim doesn't have a lot of options for building HTTP APIs with the kind of batteries-included developer experience you get in frameworks like FastAPI or Express with Swagger middleware. mummy is a fast, solid HTTP/WebSocket server library for Nim (my fork with the additions below is at github.com/isaiahpeter/mummy ) — but out of the box, it doesn't generate OpenAPI specs, validate request bodies, or give you typed path parameters. So I forked it and added those. This post walks through what I built, why, and what I learned extending an existing Nim library instead of starting from scratch. Why mummy, and why OpenAPI I wanted a Nim backend for a few projects (a contact-form API, a todo API demo) and kept missing three things I'd take for granted in other ecosystems: Auto-generated API docs — a /docs endpoint you can actually hand to someone, generated from your routes instead of hand-written. Typed path parameters — pulling id out of /users/{id} as an int without manual parsing and error handling in every handler. Request validation — rejecting a bad JSON body before it reaches your handler logic, with a schema to back it up. mummy is fast and minimal by design, which is exactly why it was worth extending rather than replacing. What I added OpenAPI spec generation. I added openapi_schema.nim and openapi_router.nim , which let you wrap routes in an OpenApiRouter and attach a summary, tags, and a response schema via schemaOf . The router serves both /openapi.json and a browsable /docs page generated from your actual route definitions — so the docs can't drift out of sync with the code the way hand-written API docs do. Typed path parameters. pathParam[T](request, "id") pulls a path segment and parses it as the type you ask for, with a clean 400 response if parsing fails. One gotcha worth flagging if you try this yourself: in this Nim version, the generic dot-call form ( request.pathParam[int]("id") ) doesn't parse — you have to call it as pathParam[int](request, "id") in