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

标签:#p

找到 12539 篇相关文章

AI 资讯

Your Agent's Memory Is a Markdown File. Let's Audit It.

Quick check: does your agent stack have a memory.md in it somewhere? An AGENTS.md ? A notes file the agent appends to when something seems worth keeping? Thought so. Mine did too. It's the pattern everyone converges on, it takes twenty minutes to build, and it genuinely works — right up until the day it hands a customer a fact that stopped being true in March. This post does three things: shows you exactly why the pattern rots (with a real-shaped sample file we'll dissect), gives you a small script to audit your own file tonight, and walks through the architecture change that actually fixes it. No vendor required for any of it. The pattern we all built Strip away the framework and every self-managed memory loop looks like this: MEMORY = Path ( " memory.md " ) def run_task ( task : str ) -> str : context = MEMORY . read_text () # 1. dump everything in result = llm ( SYSTEM + context + task ) # 2. do the actual job note = llm ( # 3. agent grades its own homework " What from this interaction is worth remembering? " " Reply with one line, or NONE. \n\n " + result ) if note . strip () != " NONE " : with MEMORY . open ( " a " ) as f : # 4. append forever f . write ( f " - { note . strip () } \n " ) return result Be fair to it first: this is human-readable, versionable, greppable, zero-infrastructure. For one agent, one job, small working set — it's honestly hard to beat. Now look at what it doesn't do. Step 4 is the entire lifecycle. Nothing in this loop ever updates, merges, expires, or questions a line once written. The file has exactly one behavior: it grows. Dissecting a six-month-old memory file Here's a condensed, realistic slice of what that loop produces by month six. Read it the way retrieval reads it — every line equally true: - Customer Acme runs their workload in us-east1 - Acme prefers Slack over email for escalations - Acme's staging env uses the legacy auth flow - Acme contact is Priya (prefers email) - The feature flag `beta_router` must stay ON for Acme -

2026-07-30 原文 →
AI 资讯

DSCI series / Rakulang CI, part2. Cro Application

In this episode I talk about developing web application based on well known cro framework and specifically how to create CI pipeline using DSCI tool. Here is example of very simple cro application (taken from cro web site): use Cro::HTTP:: Router ; use Cro::HTTP:: Server ; my $application = route { get -> { content ' text/html ', ' Hello Cro! '; } } my Cro:: Service $service = Cro::HTTP:: Server . new : : host < localhost > , : port < 10000 > , : $application ; $service . start ; react whenever signal ( SIGINT ) { $service . stop ; exit ; } First of all let's create jobs file .dsci/jobs.yaml that would contain list of jobs, in our case this is just a single job: jobs : - id : ci path : . In this case we would have just a single job that: installs apps dependencies runs web application in background runs some end to end tests using http client .dsci/job.raku run_task " install "; run_task " end-to-end "; .dsci/tasks/install/task.bash set -e cd ../ ls -l zef install . --deps-only zef install . echo "done" nohup cro run 1>app.log 2>&1 & </dev/null The first task just installs application dependencies and runs web application in background, now we can create some end to end test. For simplicity I am going to use curl http client here, but feel free choose any languages you like, for example Raku's HTTP::Tiny client, DSCI is super flexible allowing to write tasks on different languages mixing then effectively. .dsci/tasks/end-to-end/task.bash I could have made this simple one line Bash task a part of initial install task, but for claritrty and demonstration of modularity I keep as a separate one. In the future more tests may come (rathe then this trivial one) and it reasonable separate installation and testing logic. set -e # the test should fail if HTTP response is not # successful curl 127.0.0.1 127.0.0.1:10000 -f -L Ok, let's try this out. And the very first run results in ... error: 08:47:39 :: ===> Building: Digest::SHA1::Native:ver<1.0.1>:auth<zef:bduggan> 08:47:39

2026-07-30 原文 →
AI 资讯

The 300px Canvas Bug That Shrunk My React Image Editor

This is a submission for DEV's Summer Bug Smash: Clear the Lineup powered by Sentry . Project Overview I am building a browser-based text removal workspace where a user uploads an image, paints over unwanted text or objects, and sends the resulting mask to an image-editing pipeline. The mask editor uses three stacked <canvas> elements: a base canvas for the uploaded image; an overlay canvas for the painted mask; a cursor canvas for the brush preview and pointer events. All three canvases must have identical dimensions. The pointer coordinates must also map back to the same bitmap coordinate system, or the generated mask will not match the part of the image the user selected. Bug Fix On desktop, the editor had plenty of horizontal space but the uploaded image appeared inside a narrow strip surrounded by a large empty area. The result preview used the available width correctly, so the two sides of the same workspace looked unrelated. The visible symptom was a tiny image editor. The actual failure started before the image was drawn. The initialization code measured the width of the canvas wrapper: const container = canvas . parentElement if ( ! container ) return const containerWidth = container . clientWidth || 1 const containerHeight = 600 It then calculated the largest canvas size that would preserve the uploaded image's aspect ratio: const imgAspectRatio = img . width / img . height const containerAspectRatio = containerWidth / containerHeight let canvasWidth : number let canvasHeight : number if ( imgAspectRatio > containerAspectRatio ) { canvasWidth = containerWidth canvasHeight = containerWidth / imgAspectRatio } else { canvasHeight = containerHeight canvasWidth = containerHeight * imgAspectRatio } The aspect-ratio calculation was correct. The measurement it received was not. Root Cause: The Canvas Measured Itself The wrapper was a relatively positioned element with no declared width: < div className = "relative transition-all duration-500 ease-out" style = { {

2026-07-30 原文 →
AI 资讯

Emergent Design & Gall's Law: When Complex Coding Problems Dissolve Instead of Being Solved

I recently read an article by the main maintainer of InversifyJS describing the journey of rebuilding its dependency resolution algorithm . What caught my attention wasn't the performance improvements or the technical details. It was something much more familiar. As I was reading, I realized they were experiencing the exact same phenomenon I had experienced years ago while creating InversifyJS. It reminded me of something that, until now, I had never really put into words. The temptation to solve the hardest problem first Every engineer has experienced it. You're implementing a feature when you encounter a design problem that feels wrong. You know the current approach won't scale, and you know there must be a beautiful abstraction somewhere, so you stop writing code and start designing. Sometimes that's the right thing to do. Many times it isn't. While building InversifyJS, I eventually adopted a different habit. Whenever I found myself thinking, "This feels too complicated, and I can't find a simple, elegant solution right now," I decided to wait. Not because I ignored the problem, but because I didn't think I understood it well enough yet. Instead, I focused on features where I had a reasonable level of confidence. I kept improving the parts of the system that felt obvious, leaving the difficult problems untouched. At first, this almost felt irresponsible. Over time, it became one of the most valuable engineering lessons I have learned. The magic wasn't finding the solution The interesting part is that I rarely came back later with a better idea. Something stranger happened. Implementing those simpler features changed the system itself. New abstractions naturally appeared. Responsibilities became clearer. Concepts that previously seemed unrelated suddenly fit together. Eventually, I would return to the "hard" problem only to discover it wasn't hard anymore. Not because I had become smarter or because inspiration had struck overnight. The problem itself had changed

2026-07-30 原文 →
AI 资讯

How to store AI-generated images per user in object storage and delete the old ones

Use one key prefix per user, delete from the application every key you can name, and leave lifecycle rules to sweep the old temporary images nobody will ever ask for again. That's the whole design, and I've watched teams get it wrong in the same two ways for years: they either try to make the storage layer clever enough to know what a user is, or they hand the entire deletion problem to a lifecycle policy and then wonder why an account-deletion request took nine days to actually remove anything. I design data layers for a living, so I'm going to be blunt about the durability and consistency side of this rather than the upload-a-file-in-five-minutes side. Why the key layout matters more than the backend you pick Object storage has no folders. There's a flat keyspace and a delimiter convention, and every "folder" you see in a console is the UI grouping keys that share a prefix — which is good news, because it means the layout is yours to design and costs nothing to enforce. The layout I keep landing on is users/{userId}/generations/{yyyy-mm}/{uuid}.png , with a sibling users/{userId}/scratch/ prefix for renders that only exist so the browser can show a preview. Four properties come out of that shape, and they're the reason I don't get creative here. Listing a tenant's images is a single prefix query rather than a metadata scan, which matters because object stores generally don't let you search metadata server-side — you filter by prefix or you keep an index in your own database. Deleting an account becomes "enumerate one prefix, delete what's under it," so the compliance clock is something you control. The month segment keeps any single listing page from growing without bound, and it gives you a cheap way to write an age-based rule later. And the opaque UUID means the key never leaks a filename, a prompt, or an email address into a URL that might end up in a log or a referrer header. One thing I'd push back on if I saw it in review: don't put the user's email or usern

2026-07-30 原文 →
AI 资讯

How to Catch AI Hallucinations: A Copy-Paste Hallucination Checker Prompt (Tested)

You ask an AI a question. It answers in fluent, confident prose — complete with a study, a percentage, and a name. Some of it is wrong, and nothing about the wording tells you which part. That's the whole problem with hallucinations: the errors wear the same suit as the facts. The fix is not "trust it less" in some vague way. The fix is a repeatable audit step between AI wrote it and I used it . Below is a short hallucination checker prompt you can copy right now, a test run showing what it catches and what slips past it, and an honest account of where a one-liner stops being enough. What counts as an AI hallucination? Not every mistake is a hallucination. A useful working definition: a hallucination is a claim the model states as fact that has no grounding in reality or in your source material. The common shapes: Fabricated citations — a named study, expert, or paper that doesn't exist. Often dressed with a year and an institution. Plausible-but-wrong specifics — dates, version numbers, statistics that are almost right, which makes them worse. Confident category errors — mixing up two similar things (a library and a framework, one company's product and another's). Invented consensus — "experts widely agree that…" with no experts attached. The dangerous ones are the middle two. Obvious nonsense filters itself; a wrong year in a fluent paragraph does not. The copy-paste hallucination checker prompt Here is the short version, free, no strings. It works on ChatGPT, Claude, or any capable model — paste it into a fresh chat, then paste the answer you want audited: Audit the text below for hallucinations. Do not add new information. 1. Extract every factual claim as a separate numbered line. 2. Label each claim: VERIFIABLE (state how to check it), SUSPECT (state what makes it doubtful), or FABRICATION-PATTERN (named source/study/number with no citation). 3. Flag every name, number, date, and citation for manual checking. 4. Finish with the 3 claims most likely to be wrong

2026-07-30 原文 →
AI 资讯

Build a Local LLM Chatbot with Ollama and Python

Build a Local LLM Chatbot with Ollama and Python tags: python, ai, llm, tutorial tags: python, ai, llm, tutorial Build a Local LLM Chatbot with Ollama and Python Imagine typing a question into your chatbot and getting a response in milliseconds, completely offline, with zero data leaving your machine. No API keys, no monthly subscription fees, and no privacy concerns about your data being sent to a cloud server. This isn’t a futuristic dream—it’s the reality of running a Local Large Language Model (LLM) on your own computer. With the rise of tools like Ollama , building a private AI chatbot in Python has become as simple as installing a few packages and writing a short script. Let’s dive in and build one together. Why Go Local? Before we write any code, it’s worth understanding why running an LLM locally is a game-changer. Cloud-based AI services like OpenAI or Anthropic are powerful, but they come with trade-offs: you pay per token, your data is processed on their servers, and you’re dependent on their uptime. A local LLM flips this model. You download the model once, run it on your hardware, and you have full control. Ollama is the engine that makes this accessible. It’s a lightweight, open-source tool that simplifies running LLMs like Llama 3, Phi 3, or Mistral on macOS, Linux, and Windows. It handles model downloads, memory management, and inference, exposing a simple API that Python can easily interact with [1][2]. Step 1: Install Ollama and Pull a Model The first step is getting Ollama on your machine. Visit ollama.com , click Download , and install the version for your operating system [2]. Once installed, verify it’s working by opening your terminal or Command Prompt and running: ollama --version If you see a version number, you’re ready to go. Next, you need a model. Ollama supports dozens of open-source models, but for a beginner-friendly chatbot, Llama 3.2 is a great choice. It’s small, fast, and surprisingly capable. To download it, run: ollama pull llam

2026-07-30 原文 →
AI 资讯

Build a Dependency Vulnerability Scanner with Python

Build a Dependency Vulnerability Scanner with Python tags: python, security, devops, tools tags: python, security, devops, tools Build a Dependency Vulnerability Scanner with Python Your requirements.txt looks clean, but one of those dependencies might be a ticking time bomb waiting to expose your users to a data breach. You don’t need to wait for a security audit to find out—you can build your own lightweight vulnerability scanner in Python today and integrate it directly into your workflow. Security isn’t just about writing secure code; it’s about knowing what’s running in your environment. With thousands of Python packages available, the odds that you’re using a library with a known CVE (Common Vulnerabilities and Exposures) are high. Instead of relying solely on third-party tools like pip-audit or safety (which are excellent, but sometimes opaque), building your own scanner gives you full control over how vulnerabilities are detected, reported, and acted upon. Let’s build a practical, working dependency vulnerability scanner from scratch. Why Build Your Own Scanner? Existing tools like pip-audit [13], safety [10], and PySentry [4] are powerful, but they come with limitations: They may not support your specific output format (e.g., custom JSON for CI). They might not integrate cleanly with your private PyPI registry. You can’t easily tweak the logic to match your team’s risk tolerance. Building your own scanner lets you: Query the NVD (National Vulnerability Database) API directly. Parse requirements.txt , pyproject.toml , or poetry.lock files flexibly. Generate reports in any format you need (Markdown, JSON, SARIF). Fail your CI pipeline automatically when critical CVEs are found. Plus, it’s a great learning exercise in cybersecurity, API integration, and Python parsing. Step 1: Set Up Your Environment Before writing code, prepare a clean virtual environment to avoid false positives from global packages: python3 -m venv scanner-env source scanner-env/bin/activat

2026-07-30 原文 →
AI 资讯

Python Itertools: 10 Tricks for Cleaner Code

Python Itertools: 10 Tricks for Cleaner Code tags: python, programming, tips, tutorial tags: python, programming, tips, tutorial Python Itertools: 10 Tricks for Cleaner Code You’ve probably written a loop that felt like it was dragging your code into the mud. Maybe you concatenated lists with + , zipped mismatched iterables and lost data, or manually tracked indices to count items. Before you add another for loop to your script, consider this: Python’s itertools module is a hidden superpower that can turn messy iteration logic into elegant, memory-efficient, and readable one-liners. Mastering itertools doesn’t just make your code cleaner—it makes it faster, especially when working with large datasets or infinite sequences. Let’s dive into 10 practical tricks you can use today to write better Python code. 1. Chain Multiple Lists Without Copying Memory When you need to merge several lists, the + operator creates a new list in memory. That’s wasteful for large datasets. Instead, use itertools.chain() , which yields items lazily—only when you need them. from itertools import chain list1 = [ 1 , 2 , 3 ] list2 = [ 4 , 5 ] list3 = [ 6 ] merged = chain ( list1 , list2 , list3 ) for item in merged : print ( item ) # 1, 2, 3, 4, 5, 6 This approach is memory-efficient and ideal for streaming or processing huge collections [6]. 2. Zip Uneven Lists Without Losing Data The built-in zip() stops when the shortest iterable ends. But what if you want to keep going and fill in missing values? Use itertools.zip_longest() with a fillvalue . from itertools import zip_longest names = [ " Alice " , " Bob " ] ids = [ 101 , 102 , 103 ] for name , id in zip_longest ( names , ids , fillvalue = " Unknown " ): print ( f " { name } : { id } " ) Output: Alice: 101 Bob: 102 Unknown: 103 This is perfect for aligning mismatched data streams [3]. 3. Generate Infinite Counters Gracefully Need a counter that never stops? itertools.count() gives you an infinite iterator starting from a specified value. A

2026-07-30 原文 →