今日已更新 327 条资讯 | 累计 23910 条内容
关于我们

标签:#pens

找到 1564 篇相关文章

AI 资讯

Three Crashes and One Mystery: Deploying a Medical AI Model Offline for Four Nigerian Languages

I set out to deploy a fine-tuned LLM fully offline, on a mid-range Android phone, answering medical questions in Yoruba, Hausa, Igbo, and Nigerian Pidgin. No internet connection required, because that's the reality for a lot of the people this was meant to help. The model worked. Getting there broke three times, in three completely different ways, and left me with one problem I still haven't solved. The setup I fine-tuned unsloth/Llama-3.2-3B-Instruct , Unsloth's 4-bit-optimized derivative of Meta's Llama 3.2 3B, in two stages: QLoRA supervised fine-tuning on a curated dataset of 3,917 medical question-answer pairs across the four languages, followed by direct preference optimization (DPO) to sharpen response quality. SFT converged to a loss of 1.099. DPO landed a reward margin of 18.40. Then I merged to 16-bit and tried to convert to GGUF, the format llama.cpp needs to run the model on-device. That's where things started breaking. Crash 1: the tokenizer that thought it was someone else First conversion attempt. Model loads. First inference call. Instant crash: terminating due to uncaught exception of type std::out_of_range: unordered_map::at: key not found Turns out the conversion had written tokenizer.ggml.model = "llama" into the GGUF file. That field tells the runtime which tokenizer code path to use, and "llama" routes to SentencePiece. Llama 3.2 doesn't use SentencePiece. It uses BPE. The runtime was trying to read BPE tokens through a SentencePiece parser, and predictably, it found nothing where it expected something. Fix: manually set the field to "gpt2" , which routes to the correct BPE path. Crash 2: the tokenizer that couldn't decide what it was Fixed crash 1, tried again. New failure, before the model even finished converting: TypeError: Llama 3 must be converted with BpeVocab followed, after the code's fallback path kicked in, by: ValueError: Cannot instantiate this tokenizer from a slow version This one took longer to trace. Unsloth's saved tokenizer_c

2026-07-19 原文 →
AI 资讯

Building GateKeeper: Designing a Role-Based Access Control Library in Pure Go

As developers, we use authorization libraries almost every day. Whether it's a web application, an API, or an internal tool, we often rely on packages that decide who can do what. But I realized I had never actually built one. So instead of using an existing library, I decided to build my own Role-Based Access Control (RBAC) library in Go using only the standard library. This project eventually became GateKeeper v1.0.0. Why I Built One As a beginner in backend development, I wanted to get exposure on how to make public APIs and how to make them work under the hood. It also made me fight my old syntax habits. Go has strict error handling, which I also learned. I built it because I wanted to understand the engineering decisions behind public libraries. Instead of watching another tutorial, I built it myself. Project Goals Before writing any code, I brainstorm the architecture in my mind. No external library used, only the standard Go library. Keeping the public APIs simple and easy to read for developers to use. Write tests for each and every function, no matter how small. These constraints forced me to think more carefully about the design instead of depending on external packages. The Core Model Engine ├── Users ├── Roles └── Permissions Relationships are straightforward: Users | V Roles | V Permissions A user can have multiple roles, and roles can have multiple permissions. Permissions describe access to a resource and an action. Designing The API One thing I learned the hard way is that API design matters more than the implementation itself. I wanted to keep the library easy to read even without documentation. The public API ended up looking something like this: CreateUser() CreateRole() CreatePermission() AssignRole() AssignPermission() Can() DeleteUser() DeleteRole() DeletePermission() RenameUser() RenameRole() I had to redesign the API many times before eventually coming up with the final one. The time spent fighting the design was worth it. It taught me API de

2026-07-19 原文 →
AI 资讯

Your LLM can't actually watch video. Here's the smallest fix (MIT)

Every model card says "multimodal". Then you hand the model a real video file and discover what that means in practice: ChatGPT reads the subtitle track, Claude doesn't accept video files at all. The model narrates a video it mostly never saw. I unpack viral videos daily for my own content work, so I couldn't route around this. I built a small tool instead. The mechanism claude-real-video converts a video into three things an LLM can genuinely read: Scene-aware sampled frames — ffmpeg scene scores decide where to sample, so you get a frame when the picture changes, not every N seconds. An --adaptive flag handles slow deformations (a real user bug report: fixed thresholds missed squash/stretch morphs entirely). A timestamped transcript — whisper by default; if faster-whisper is installed it runs in-process and several times faster, with automatic fallback. One MANIFEST timeline — frames and transcript merged into a single file, so the model follows the video in order instead of guessing from fragments. A --text-anchors flag force-samples frames at subtitle cues so on-screen text never falls between frames. Then you point any LLM at the output folder — Claude, GPT, Gemini, or a local model. No API of mine in the middle, everything runs on your machine. Usage pip install claude-real-video crv "video.mp4" -o out Honest limitations Not real-time — a 90-second video takes about 1–2 minutes all-in on an M-series Mac. Frame sampling can still miss motion between frames; the flags above patch the worst cases, both born from real GitHub issues. It's MIT, currently at 1,731 stars with ~8k installs last month, which taught me the problem was never just mine: https://github.com/HUANGCHIHHUNGLeo/claude-real-video

2026-07-19 原文 →
AI 资讯

DocuSeal: An Open-Source Alternative for Digital Document Signing and Processing

What Changed DocuSeal has emerged as an open-source platform for digital document signing and processing. This project offers a self-hostable alternative to commercial services, allowing organizations to manage document workflows, eSignatures, and form filling within their own infrastructure. The platform is designed to be accessible, mobile-optimized, and integrates with existing systems through APIs and webhooks. Technical Details DocuSeal provides a comprehensive set of features for digital document management. Key functionalities include a WYSIWYG PDF form fields builder that supports 12 field types, such as Signature, Date, File, and Checkbox. It accommodates multiple submitters per document and automates email notifications via SMTP. For file storage, DocuSeal offers flexibility, supporting local disk storage as well as cloud providers like AWS S3, Google Storage, and Azure Cloud. The platform implements automatic PDF eSignature generation and includes a mechanism for PDF signature verification, addressing security and compliance requirements. User management is integrated, and the UI is mobile-optimized, supporting 7 UI languages with signing capabilities in 14 languages. Integration with other systems is facilitated through a robust API and webhooks. Deployment options are varied, catering to different infrastructure preferences. DocuSeal can be deployed on cloud platforms such as Heroku, Railway, DigitalOcean, and Render. For containerized environments, Docker images are available, allowing for deployment via docker run commands. By default, the Docker container utilizes an SQLite database, but it can be configured to use PostgreSQL or MySQL by setting the DATABASE_URL environment variable. Docker Compose configurations are also provided, enabling deployment with custom domains and automatic SSL certificate issuance via Caddy. Pro features, available through commercial offerings, extend the platform's capabilities to meet business needs. These include compa

2026-07-19 原文 →
AI 资讯

Why I Stopped Self-Hosting AI Models (And You Probably Should Too)

I spent three months and about $500 on GPU rental trying to host my own LLM. I had a spare RTX 3090, I was deep in the open-source hype, and I was convinced that running my own model was the only way to get privacy, control, and—let’s be honest—bragging rights. I ended up switching to an API that costs me less than a dollar per month for my use case. Here’s what I learned, and why I think most developers should stop self-hosting AI models. The Siren Song of Self-Hosting The argument for self-hosting sounds great: Privacy : Your data never leaves your machine. Control : You can fine-tune, tweak, or swap models whenever you want. No vendor lock-in : You’re not at the mercy of OpenAI or Google changing their pricing or policies. Open source ethos : It’s the “right” way to do things. I bought into all of it. I set up Ollama, downloaded Llama 2 7B, then 13B, then Mixtral 8x7B. I spent weekends wrestling with Docker, CUDA versions, and VRAM limits. I felt like a real engineer. But the reality was different. The Hidden Costs My $500 was just the start. I rented cloud GPUs because my 3090 wasn’t enough for the models I wanted. A single A100 on AWS costs about $3.50 per hour. For a model like Llama 2 70B, you need at least 48GB VRAM, which means a multi-GPU setup or a high-end instance. Here’s a quick breakdown of what I actually spent over three months: Item Cost GPU rental (spot instances) ~$350 Storage for model weights ~$30 Time debugging (conservative) 40 hours Power/electricity (home GPU) ~$40 Total ~$420+ And I never got it running reliably. The 70B model would crash after a few hours. The 13B model was decent but slow—about 10 tokens per second on my 3090. For a chat app, that’s painful. Compare that to an API call: import openai client = openai . OpenAI ( api_key = " sk-... " , base_url = " https://api.tai.shadie-oneapi.com/v1 " ) response = client . chat . completions . create ( model = " gpt-4o-mini " , messages = [{ " role " : " user " , " content " : " What ' s

2026-07-19 原文 →
AI 资讯

A Hands-On Guide to kalbee: Your First Kalman Filter (and Beyond)

Everything you need to go from pip install to a working multi-object tracker, one runnable snippet at a time. kalbee is a Python library for state estimation — the art of recovering a clean signal (position, velocity, temperature, whatever you're measuring) from noisy sensor data. This guide walks through it from the ground up. Every code block runs as-is; copy them into a file and follow along. Install pip install kalbee The only runtime dependencies are NumPy and SciPy. Optional extras add object-detection ( pip install "kalbee[yolo]" ) and plotting ( pip install "kalbee[viz]" ) support. The one idea you need: predict and update Every filter in kalbee works the same way. You alternate between two steps: predict() — advance the state forward in time using a motion model ("where do I think the object is now?"). update(z) — correct that prediction with a new measurement z ("what does the sensor actually say?"). The filter tracks two things: the state x (your best estimate) and the covariance P (how uncertain that estimate is). You read them back via kf.x and kf.P . Your first filter Let's track an object moving at roughly constant velocity, measuring only its (noisy) position. Instead of hand-building matrices, we use kalbee's ready-made models : import numpy as np from kalbee import KalmanFilter , rmse from kalbee.models import constant_velocity , position_measurement_model dt = 1.0 # Motion model: state is [position, velocity] F , Q = constant_velocity ( dt = dt , process_var = 0.01 , n_dims = 1 ) # Measurement model: we observe position only, with noise variance 4.0 H , R = position_measurement_model ( order = 1 , n_dims = 1 , measurement_var = 4.0 ) # Simulate a noisy trajectory rng = np . random . default_rng ( 0 ) pos , vel = 0.0 , 1.0 truths , measurements = [], [] for _ in range ( 50 ): pos += vel * dt truths . append ( pos ) measurements . append ( pos + rng . standard_normal () * 2.0 ) # std 2.0 -> var 4.0 # Create the filter: start at zero with high uncert

2026-07-19 原文 →
AI 资讯

Looking for Contributors: Building FaultPlane, a High-Performance System Engine (Good First Issues Open!)

Why FaultPlane Exists Modern low-latency infrastructure demands bypassing heavy disk serialization. FaultPlane addresses this by implementing an eBPF-driven architecture designed for zero-copy memory management. We are building the core engine along with an interactive Next.js operations dashboard, and we need your expertise to accelerate development. Our Technical Stack Core Infrastructure: Go (Golang), eBPF, Kernel-space architecture, PCIe DMA abstractions Operations Dashboard: Next.js, Tailwind CSS, TypeScript Active Challenges (Good First Issues Available) We have organized our current roadmaps into highly accessible, well-documented GitHub issues. Contributors of all skill levels are welcome to claim tasks: Architecture & Documentation: Migration of repository references and architectural namespaces from AgentMesh to FaultPlane. Frontend Engineering: Implementation of a minimalist dashboard grid layout with command palettes, responsive sidebar navigation, and multi-region panel toggles. System Programming: Implementation of lock-free ring buffer memory allocators using sync/atomic flags, and eBPF sockmap TCP stream splicing. How to Get Your First Pull Request Merged Explore our current open tracker list: https://github.com/devloperdevesh/FaultPlane/issues Leave a comment on the issue you wish to claim, and it will be assigned to your profile immediately. If you require setup assistance or technical clarification, start a thread under our discussions tab or leave a query right here in the comments. Join us in building a high-performance open-source system engine.

2026-07-19 原文 →
AI 资讯

Why I Stopped Copy-Pasting Repositories and Started Building My Own Starter CLI

Every developer has a "starter project." Some keep a GitHub template. Some duplicate their previous SaaS project. Some run create-next-app and spend the next two hours installing the same dependencies, configuring the same tools, and recreating the same folder structure. I was in the second group. Every new project started the same way. bun create next-app Then came the checklist. Install Tailwind CSS. Configure Biome. Add shadcn/ui. Organize folders. Set up a UI library. Configure TypeScript. Add environment files. Set up a monorepo. Copy utility functions. Configure path aliases. Install development tools. None of these tasks were difficult. They were just repetitive. After starting enough projects, I realized something: I wasn't building products. I was rebuilding the same foundation over and over again. The Starter Kit Trap Like many developers, I created a "starter repository." Whenever I wanted to build something new, I'd clone it. It worked... until it didn't. Eventually I had multiple starter repositories. One for a monorepo. One for a standalone project. One with authentication. One without authentication. One for experiments. One that was already outdated. Keeping them synchronized became its own maintenance project. Fix a bug in one. Forget to fix it in another. Upgrade Next.js in one repository. Forget the rest. The more starters I created, the less useful they became. Why Existing Starters Didn't Quite Fit There are already fantastic starter kits in the ecosystem. Some focus on minimalism. Others include every feature imaginable. The problem wasn't that they were bad. The problem was that they optimized for someone else's workflow. Every project I build starts with almost the same stack. Next.js TypeScript Bun/pnpm Tailwind CSS v4 shadcn/ui Biome Production-ready project structure I didn't want to answer twenty configuration questions every time I scaffolded a project. I wanted one command. npx create-notils my-app …and be ready to start building. Opini

2026-07-19 原文 →
AI 资讯

A tiny engine for generating file trees

I just tagged 1.0.0 of ts-treegen, a small TypeScript library for describing file structures as data and writing them to disk. If you've ever built a CLI, a scaffolding tool, or anything that needs to generate a bunch of files and folders, you know the usual approach: a pile of fs.writeFileSync calls, manual path joins, and conditional logic scattered everywhere. ts-treegen is my attempt at making that feel less like plumbing and more like just describing what you want. What it looks like import { file , dir , emit , plan } from " ts-treegen/node " ; const files = await emit ( file ( " README.md " , " # My New App " ), dir ( " src " , file ( " index.ts " , " console.log('hello'); " )), ); const p = await plan ( files , { targetDir : " ./output " }); await p . run (); file() and dir() build a tree. emit() resolves it. plan() figures out what needs to be written and gives you a chance to inspect it before anything touches disk. That's the whole API. Conditional files don't need any special syntax either. It's just JavaScript: isProd && file ( " .env.production " , " NODE_ENV=production " ); No template tags, no wrapper nodes to learn. If a value is falsy, it's filtered out. Why I built it this way The goal from the start was to keep the surface area small enough that you could hold the whole API in your head after reading the README once. I went through a few iterations before landing here, and each one was mostly about removing things rather than adding them. Conflict resolution collapsed down to a single overwrite flag. Copy helpers got cut because fs.cp already does the job. Custom error types got replaced with things you'd actually reach for in normal code. Every feature I kept had to earn its place by solving something real, not just being possible to build. Along the way the library also became runtime-agnostic. The core has zero dependencies and works against a small FileSystem interface, so I/O is fully pluggable. ts-treegen/node wires up Node's fs/promises fo

2026-07-19 原文 →
AI 资讯

What encryption actually is, in plain words.

I’ve read the word “encrypted” on more apps than I can count, and most of the time it tells you almost nothing. Here’s what it really means, the way I’d explain it to a friend. Every app you use will tell you your data is encrypted. It’s on the login screen, the pricing page, the little padlock in the corner of the browser. And because it’s on everything, it’s stopped meaning much. I’ve spent more time on that one word than I’d care to admit, building a notes app where it actually has to be true, so here’s how I think about it. No maths. No padlock pictures. Underneath, encryption is an old and simple idea. You take a message, turn it into nonsense nobody can read, and make sure only the right person can turn it back. That’s the lot. Everything after that is detail about how good the nonsense is, and who’s allowed to undo it. The whole thing in one sentence Encryption takes something readable and mixes it into a mess that means nothing on its own. A matching key turns the mess back into the original. No key, and the mess stays a mess. The readable version is called plain-text. The mixed version is called cipher-text. That’s the entire vocabulary you need to know. Encryption turns plain-text into cipher-text, decryption is turning it back. A note is just text until you scramble it Say you’ve got a note on your phone, “dentist Thursday, 3pm”. Stored as it is, anyone who gets at the file reads it straight off. A thief with your unlocked phone. An app you handed too many permissions to. A company keeping a copy on its servers. All of them see “dentist Thursday, 3pm”. Encrypt it and that same note might sit on the disk as 9f2ac1b0e7..., a run of characters that means nothing. The appointment is still in there, in the sense that the right key brings it back, but on its own it tells a snoop nothing. Not the time, not the day, not that it was ever about a dentist. People reach for a padlock to explain this and I’ve never liked it. A padlock just stops you getting to the thi

2026-07-18 原文 →