The Zero-Trust Build project is scheduled from Jan-Aug 2025 and
centers on the FreeBSD build process, and in particular, release
building. The primary goal of this work is to enable the entire
release process to run without requiring root access, and that build
artifacts build reproducibly – that is, that a third party can build
bit-for-bit identical artifacts.
Additionally, the project aims to enhance build process
documentation, ensuring that release building is straightforward and
does not require specialized knowledge. The work is targeted for
completion prior to the release of FreeBSD 15.0.
The Foundation says that updates should not impact users of FreeBSD
release images, but it may have an impact on developers basing
projects or products on FreeBSD that make modifications to its release
process.
The proposal to add a more general facility for string formatting to
Python, which we looked at in August 2024,
has changed a great deal since, so it merits another look. The
changes take multiple forms: a new title for PEP
750 (“Template Strings”), a different mechanism for creating and using templates,
a new Template type to hold them, and several additional authors for the PEP.
Meanwhile, one controversial part of the original proposal, lazy evaluation
of the interpolated values, has been changed so that it requires an
explicit opt-in (via lambda);
template strings are a generalization of f-strings and lazy evaluation was seen by some
as a potentially confusing departure from their behavior.
In this post, I’ll look at another AI technology, agents, and show you how I built an AI agent that answers questions about hard drive reliability based on over 11 years of raw data from our Drive Stats franchise.
The Drive Stats dataset is ideal for this kind of work. It’s a real-world dataset, but, it only weighs in at around 500 million records consuming about 20GB of storage in Parquet format (“only” being a relative term), so you can use it with big data and AI tools on a laptop in a reasonable amount of time rather than spinning up an expensive virtual machine (VM) and/or spending days waiting for an operation to complete. As an example, converting the entire Drive Stats data set from CSV to Parquet using a Python app on my MacBook Pro takes a couple of hours. On the same hardware, converting a terabyte-scale data set would take about four days.
Speaking of Drive Stats
The Drive Stats 2024 report comes out February 11, and we’re hosting a LinkedIn Live event where Andy Klein, resident Drive Stats guru, will share highlights. Register today to save your spot.
You can use these same techniques with any large dataset, from healthcare to ecommerce to financial services. In this example, we’re working with a single table, but you could adapt the sample code to a data lake comprising any number of tables.
What is an AI agent?
In the spirit of the times, I posed this question to ChatGPT. Its answer:
An AI agent is a software system designed to autonomously perform tasks or make decisions based on its environment and goals. It leverages artificial intelligence techniques—such as machine learning, reasoning, and natural language processing—to process information, make decisions, and take actions to achieve specific objectives.
Key components of an AI agent include:
Perception: The ability to sense and understand its environment. This could be through sensors, input data, or other means of gathering information.
Reasoning/decision-making: The core processing mechanism that helps the agent interpret its environment, make decisions, and plan actions. It could use various algorithms, such as decision trees, reinforcement learning, or neural networks.
Action: Once the agent has analyzed the environment and made a decision, it takes action to achieve its goal, whether it’s performing an operation, giving a recommendation, or interacting with another system.
Learning: Some AI agents can adapt over time, improving their decision-making and actions based on experience (via reinforcement learning, supervised learning, etc.).
AI agents can range from simple systems, like chatbots or virtual assistants, to more complex systems like autonomous vehicles, robots, or financial trading algorithms.
In general, the term “agent” emphasizes the idea of autonomy—the agent operates independently, often with the ability to learn, adapt, and make decisions based on changing conditions without direct human intervention.
In this example, the agent’s environment is a database containing the Drive Stats data (more on that below), and I want it to perform the following tasks:
Based on a natural language question, such as “Which drive has the lowest annual failure rate?”, generate a SQL query that retrieves data that will help answer the question.
Execute that query against the Drive Stats dataset.
Based on the query results, either create a new query that better answers the question, or generate a natural language answer.
Now I’ve established that my agent will be writing a SQL query, the next question is, “What will it be querying?” I’ve written about querying the Drive Stats dataset before; in that blog post I explained how I wrote a Python script to convert the Drive Stats data from the CSV format in which we publish it to Apache Parquet, a column-oriented file format particularly well-suited for storing tabular data for use in analytical queries, and upload it to a Backblaze B2 Bucket using the Apache Hive table format. There’s a broad ecosystem of tools and platforms that can manipulate Parquet data in object storage (for example, Apache Spark and Snowflake) and I chose Trino, the open source distributed SQL engine that forms the basis for Amazon Athena, to execute queries against the data.
I could have used the same technologies for this exercise, but I decided to add Apache Iceberg to the mix. While Parquet is a file format that specifies how tabular data is stored in files, Iceberg is a table format that governs how those files can be combined and interpreted as a database table. Iceberg provides a number of advantages over Hive as a table format, including better performance and much more flexible data partitioning.
What is partitioning?
Partitioning splits a dataset on one or more column values, easing data management and improving performance when a query includes a partition column.
Partitioning by year and month makes sense for the Drive Stats dataset—the resulting Parquet files are in the hundreds of megabytes, the sweet spot for Parquet data. To apply this partitioning to the Drive Stats data using the Hive table format, I had to create otherwise redundant month and year columns from the existing date column, complicating the schema.
Iceberg, by contrast, supports hidden partitioning, allowing you to apply a transformation to a column value to produce a partition value without adding any new columns. With the Drive Stats data, that meant I could simply define the partitioning as month(date) (the resulting value being the number of months since 1/1/1970, rather than an integer between 1 and 12), with no need to create any additional columns.
LangChain’s SQLDatabase class provides access to databases via the SQLAlchemy open-source Python library. The demo code obtains a SQLDatabase instance by providing a URI containing the trino scheme, a username and the location of the database node:
db = SQLDatabase.from_uri('trino://admin@localhost:8080/iceberg/drivestats')
Note: In this and other code excerpts in this blog post, I’ve omitted extraneous “boilerplate” code. As mentioned above, the full source code is available in the ai-agent-demo repository.
As you can infer from the localhost domain name, I’m running Trino on my laptop. I’m actually running it in Docker, using the Iceberg/Hive Docker Compose script from the trino-getting-started-b2 repository. I’ll dive into that example in a future blog post.
A simple query confirms that we have a successful database connection:
db.run("SELECT COUNT(*) FROM drivestats")
'[(537220724,)]'
As the result conveys, there are over 537 million rows in the Drive Stats dataset.
Each row contains the metrics collected from a single drive in the Backblaze fleet on a specific day. The schema has evolved over time, but, currently, the following columns are included:
date: The date of collection.
serial_number: The unique serial number of the drive.
model: The manufacturer’s model number of the drive.
capacity_bytes: The drive’s capacity in bytes.
failure: 1 if this was the last day that the drive was operational before failing, 0 if all is well.
pod_slot_num: The physical location of a drive within a storage server, as an integer from 0 to 59. The specific slot differs based on the storage server type and capacity: Backblaze (45 or 60 drives), Dell (26 drives), or Supermicro (60 drives).
pod_id: There are 20 storage servers in each Backblaze Vault. The pod_id is a numeric field with values from 0 to 19 assigned to each of the 20 storage servers.
vault_id: All data drives are members of a Backblaze Vault. Each Vault consists of either 900 or 1,200 hard drives divided evenly across 20 storage servers. The Vault is a numeric value starting at 1,000.
cluster_id: The name of a given collection of storage servers logically grouped together to optimize system performance, formatted as a numeric field with up to two digits. Note: At this time the cluster_id is not always correct; we are working on fixing that.
datacenter: The Backblaze data center where the drive is installed, currently one of ams5 (Amsterdam, Netherlands), iad1 (Reston, Virginia), phx1 (Phoenix, Arizona), sac0 (Sacramento, California), sac2 (Stockton, California) or, now live, yyz1, our new Toronto, Ontario, data center.
is_legacy_format: Currently 0, but may change in future as more fields are added.
A collection of SMART attributes. The number of attributes collected has risen over time; currently we store 93 SMART attributes in each record, each one in both raw and normalized form, with field names of the form smart_n_normalized and smart_n_raw, where n is between 1 and 255.
# OPENAI_API_KEY must be defined in the .env file
load_dotenv()
llm = ChatOpenAI(model="gpt-4o-mini")
Now we need a system prompt template. We’ll combine this with the database schema and a natural language question to form the prompt that we send to OpenAI. As in the LangChain tutorial, I’m using a prompt from the LangChain Prompt Hub:
This is the prompt template text, with the placeholders shown in {braces}:
================================ System Message ================================
Given an input question, create a syntactically correct {dialect} query to run to help find the answer. Unless the user specifies in his question a specific number of examples they wish to obtain, always limit your query to at most {top_k} results. You can order the results by a relevant column to return the most interesting examples in the database.
Never query for all the columns from a specific table, only ask for a few relevant columns given the question.
Pay attention to use only the column names that you can see in the schema description. Be careful to not query for columns that do not exist. Also, pay attention to which column is in which table.
Only use the following tables:
{table_info}
Question: {input}
Notice how the template requires you to specify the correct SQL dialect, constrains the number of results returned, and encourages the model to not hallucinate column names that do not exist in the schema.
A helper function populates the prompt template, sends it to the model, and returns the generated SQL query:
We can test the helper function by calling it directly with a Python dictionary containing a simple question:
question = {"question": "How many drives are there?"}
query = write_query(question)
The resulting query dictionary does indeed contain a valid SQL query, but it won’t give us the answer we are looking for.
{'query': 'SELECT COUNT(*) AS drive_count FROM drivestats'}
That query will tell us how many rows there are in the dataset, rather than how many drives. We supplied the database schema to the model, but we haven’t given it any information on the semantics of the columns in the drivestats table. We can provide a bit more detail to obtain the correct query:
question = {"question": "Each drive has its own serial number. How many drives are there?"}
query = write_query(question)
This time, the generated SQL query is correct:
{'query': 'SELECT COUNT(DISTINCT serial_number) AS total_drives FROM drivestats'}
As you can see, it’s important to check the output of AI models—they can and do generate unexpected results.
A second helper function executes the query against the database:
We can test it using the (correct) generated query:
result = execute_query(query)
{'result': '[(430464,)]'}
We need one more helper function, to pass the result set to the model and have it generate a natural language response. This time, we define our own prompt:
def generate_answer(state: State):
prompt = (
"Given the following user question, corresponding SQL query, "
"and SQL result, answer the user question.\n\n"
f'Question: {state["question"]}\n'
f'SQL Query: {state["query"]}\n'
f'SQL Result: {state["result"]}'
)
response = llm.invoke(prompt)
return {"answer": response.content}
Again, we can test it in isolation. Notice that we have to provide the question and query, as well as the result so that the model has the context it needs:
We’ve combined the write_query and execute_query steps into a graph object that can run agent-generated queries. I’ll quote the security note from the LangChain tutorial on the inherent risks in doing so:
Building Q&A systems of SQL databases requires executing model-generated SQL queries. There are inherent risks in doing this. Make sure that your database connection permissions are always scoped as narrowly as possible for your chain/agent’s needs. This will mitigate though not eliminate the risks of building a model-driven system. For more on general security best practices, see here.
In this example, we are querying a public dataset, and I followed best practice by configuring Trino’s Iceberg connector with a read-only application key scoped to the bucket containing the Drive Stats Iceberg tables.
Now let’s stream a new question through the flow. This mode of operation displays the output of each step as it is executed, essential for understanding the flow’s behavior, particularly when it is behaving unexpectedly. The model returns structured text in Markdown format. With a couple of lines of code to extract the message from the step variable, we can use the display_markdown function to render each step’s output:
for step in graph.stream(
{"question": "Each drive has its own serial number. How many drives did each data center have on 9/1/2024"}, stream_mode="updates"
):
# unwrap the step value to get the markdown message
state = one(step.values())
message = one(state.values())
display_markdown(message, raw=True)
This is the model’s output, and it gives us three different messages. I’ve separated them with a horizontal line for clarity:
SELECT datacenter, COUNT(DISTINCT serial_number) AS drive_count FROM drivestats WHERE date = ‘2024-09-01’ GROUP BY datacenter ORDER BY drive_count DESC LIMIT 10
Error: (trino.exceptions.TrinoUserError) TrinoUserError(type=USER_ERROR, name=TYPE_MISMATCH, message=”line 3:12: Cannot apply operator: date = varchar(10)”, query_id=20250113_221649_00214_bsut5) [SQL: SELECT datacenter, COUNT(DISTINCT serial_number) AS drive_count FROM drivestats WHERE date = ‘2024-09-01’ GROUP BY datacenter ORDER BY drive_count DESC LIMIT 10] (Background on this error at: https://sqlalche.me/e/20/f405)
The SQL query encountered an error because it attempted to compare a date column with a string in the format ‘YYYY-MM-DD’. Specifically, the error message indicates that the date column is of a different type (likely not a string), which is causing the type mismatch.
To answer the user question about how many drives each data center had on 9/1/2024, the SQL query needs to be corrected. Here’s the revised query:
SELECT datacenter, COUNT(DISTINCT serial_number) AS drive_count
FROM drivestats
WHERE date = DATE '2024-09-01'
GROUP BY datacenter
ORDER BY drive_count DESC
LIMIT 10
This corrected query uses the DATE keyword to ensure that the date string is properly interpreted as a date type, which should resolve the type mismatch error. If executed successfully, this query will provide the count of distinct drives in each data center for the specified date. However, without executing the corrected query against the database, we cannot provide the exact counts.
As you can see in the output from the first step, the model generated an invalid query, comparing a date to a string, despite the database schema being included in the prompt. The output of the second step contains the resulting error message from the database, while the third step contains the model’s diagnosis of the error.
This exchange highlights a limitation of a flow that is simply a linear series of steps, such as write_query, execute_query, and generate_answer. We cannot rely on the model to generate a valid SQL query, although it is able to point the way towards resolving its error.
Creating a ReAct AI agent with LangGraph
The LangGraph framework gives you the capability to create AI agents based on arbitrarily complex logic. In this article, I’ve used its prebuilt ReAct (Reason+Act) agent, since it neatly demonstrates the agent concept, rewriting the SQL query repeatedly in response to database errors.
There are three steps to creating the agent. The first is to create an instance of LangChain’s SQLDatabaseToolkit, passing it the database and model, and obtain its list of tools:
================================ System Message ================================
You are an agent designed to interact with a SQL database.
Given an input question, create a syntactically correct {dialect} query to run, then look at the results of the query and return the answer.
Unless the user specifies a specific number of examples they wish to obtain, always limit your query to at most {top_k} results.
You can order the results by a relevant column to return the most interesting examples in the database.
Never query for all the columns from a specific table, only ask for the relevant columns given the question.
You have access to tools for interacting with the database.
Only use the below tools. Only use the information returned by the below tools to construct your final answer.
You MUST double check your query before executing it. If you get an error while executing a query, rewrite the query and try again.
DO NOT make any DML statements (INSERT, UPDATE, DELETE, DROP etc.) to the database.
To start you should ALWAYS look at the tables in the database to see what you can query.
Do NOT skip this step.
Then you should query the schema of the most relevant tables.
Now we can create an instance of the prebuilt agent:
Again, we can stream the agent’s execution to show us each step of its operation.
for step in agent_executor.stream(
{"messages": [{"role": "user", "content": "Each drive has its own serial number. How many drives did each data center have on 9/1/2024?"}]},
stream_mode="values",
):
step["messages"][-1].pretty_print()
The output from this flow is over 300 lines long; I posted it in its entirety as a Gist, but I’ll summarize the steps here:
Question: Each drive has its own serial number. How many drives did each data center have on 9/1/2024?
The model calls the “list tables” tool.
The list tables tool responds with a single table name, drivestats.
The model calls the “get schema” tool, passing it the table name.
The get schema tool responds with the schema and three sample rows from the drivestats table.
The model submits a query to the “query checker” tool: SELECT datacenter, COUNT(serial_number) AS drive_count FROM drivestats WHERE date = '2024-09-01' GROUP BY datacenter ORDER BY drive_count DESC LIMIT 10;
The query checker responds with the checked query, which is the same as its input. Note that the query checker only checks the SQL query’s syntax. The query contains the same data type mismatch as the query we generated earlier, as well as another error, as we’re about to discover.
The model submits the query to the “query executor” tool.
The query executor responds with a syntax error—Trino does not allow a trailing semi-colon on the query.
The model submits a modified query to the query checker tool: SELECT datacenter, COUNT(serial_number) AS drive_count FROM drivestats WHERE date = '2024-09-01' GROUP BY datacenter ORDER BY drive_count DESC LIMIT 10
The query checker responds with the checked query, which is the same as its input.
The model submits the query to the “query executor” tool.
The query executor responds with a type mismatch error since the query tries to compare a string value with a date column.
The model submits a query with the necessary DATE type identifier to the query checker tool: SELECT datacenter, COUNT(serial_number) AS drive_count FROM drivestats WHERE date = DATE '2024-09-01' GROUP BY datacenter ORDER BY drive_count DESC LIMIT 10
The query checker responds with the checked query, which is the same as its input.
The model submits the query to the “query executor” tool.
The query executor responds with a result set: [ ('phx1', 89477), ('sac0', 78444), ('sac2', 60775), ('', 24080), ('iad1', 22800), ('ams5', 16139) ]
The model returns a message containing the answer:
On September 1, 2024, the following datacenters had the specified number of drives:
These results show the datacenters with their respective drive counts.
Now let’s see if the model can calculate the annualized failure rate of a drive model. We’ll use the Seagate ST4000DM000, just because that is the drive model with the most days of operation in the dataset.
for step in agent_executor.stream(
{"messages": [{"role": "user", "content": "Each drive has its own serial number. What is the annualized failure rate of the ST4000DM000 drive model?"}]},
stream_mode="values",
):
step["messages"][-1].pretty_print()
The annualized failure rate (AFR) for the ST4000DM000 drive model can be calculated using the following information:
– Total failures: 5,791
– Total drives: 37,040
– Time period: from May 10, 2013, to September 30, 2024, which is approximately 11.35 years.
The formula for calculating the annualized failure rate is:
Plugging in the numbers:
Therefore, the annualized failure rate (AFR) of the ST4000DM000 drive model is approximately 13.77%.
It’s impressive that the agent shows its working so comprehensively, but, unfortunately, it arrives at the wrong answer. Those drives were not all running for the entire span of the Drive Stats dataset. The correct calculation involves determining the number of days with data for those drives and dividing it by 365 to get the correct number of years’ operation.
It’s clear that the model is not able to answer questions on drive reliability given the data available to it so far. The solution lies in prompt engineering—providing more context on the semantics of the data in the system prompt.
We can extend the default AI agent system prompt template to include specific instructions on working with the Drive Stats dataset:
prompt_template.messages[0].prompt.template += """
Each row of the drivestats table records one day of a drive’s operation, and contains the serial number of a drive, its model name, capacity in bytes, whether it failed on that day, SMART attributes and identifiers for the slot, pod, vault, cluster and data center in which it is located.
Use this calculation for the annualized failure rate (AFR) for a drive model over a given time period:
1. **drive_days** is the number of rows for that model during the time period.
2. **failures** is the number of rows for that model during the time period where **failure** is equal to 1.
3. **annual failure rate** is 100 * (**failures** / (**drive_days** / 365)).
Use double precision arithmetic in the calculation to avoid truncation errors. To convert an integer **i** to a double, use CAST(**i** AS DOUBLE)
Note that the date column is a DATE type, not a string. Use the DATE type identifier when comparing the date column to a string.
Do not add a semi-colon suffix to SQL queries."""
Now, when we ask the same question on the annual failure rate of the ST4000DM000 drive model, the AI agent generates a correct SQL query and a more concise, and correct, final response (you can inspect the full output here).
SELECT 100 * (CAST(COUNT(CASE WHEN failure = 1 THEN 1 END) AS DOUBLE) / (COUNT(*) / 365)) AS annual_failure_rate
FROM drivestats
WHERE model = 'ST4000DM000'
The annual failure rate (AFR) for the ST4000DM000 drive model is approximately 2.63%.
response = agent_executor.invoke(
{"messages": [{"role": "user", "content": "What was the annual failure rate of the ST8000NM000A drive model in Q3 2024?"}]}
)
response['messages'][-3].pretty_print()
display_markdown(response['messages'][-1].content, raw=True)
The query makes sense, and the response agrees with the table in the blog post:
SELECT 100 * (CAST(SUM(failure) AS DOUBLE) / (COUNT(*) / 365)) AS annual_failure_rate
FROM drivestats
WHERE model = 'ST8000NM000A' AND date >= DATE '2024-07-01' AND date < DATE '2024-10-01'
The annual failure rate (AFR) of the ST8000NM000A drive model in Q3 2024 is approximately 1.61%.
Interestingly, this time the SQL query used SUM(failure) to count the number of failures, rather than the equivalent, but rather long-winded COUNT(CASE WHEN failure = 1 THEN 1 END) it used in the previous query. Also, looking at the full response, we can see that, as directed by the custom prompt, the agent generated the correct syntax for comparing dates, so it didn’t need to correct and retry any queries.
Finally, let’s ask a more convoluted question, including the constraints given in the blog post:
response = agent_executor.invoke(
{"messages": [{"role": "user", "content": "Considering only drive models which had at least 100 drives in service at the end of the quarter and which accumulated 10,000 or more drive days during the quarter, which drive had the most failures in Q3 2024, and what was its failure rate?"}]}
)
response['messages'][-3].pretty_print()
display_markdown(response['messages'][-1].content, raw=True)
Again, the AI agent is able to generate a valid SQL query, this time including a subquery, and its response matches the data from the blog post exactly:
WITH drive_stats AS (
SELECT model,
COUNT(DISTINCT serial_number) AS drive_count,
COUNT(*) AS drive_days,
COUNT(CASE WHEN failure = 1 THEN 1 END) AS failures
FROM drivestats
WHERE date >= DATE '2024-07-01' AND date < DATE '2024-10-01'
GROUP BY model
HAVING COUNT(DISTINCT serial_number) >= 100 AND COUNT(*) >= 10000
)
SELECT model,
failures,
100 * (CAST(failures AS DOUBLE) / (CAST(drive_days AS DOUBLE) / 365)) AS failure_rate
FROM drive_stats
ORDER BY failures DESC
LIMIT 10
The drive model with the most failures in Q3 2024 is the TOSHIBA MG08ACA16TA, which had 181 failures. Its failure rate during this period was approximately 1.84%.
Closing thoughts
My experience building an AI agent was astonishment at its ability to correctly generate quite complex SQL queries based on natural language instructions, tempered with frustration at its limitations, particularly the way that it would confidently generate an incorrect response, rather than saying “I’m sorry, but I don’t know how to do that.” Your AI agent development process should include generous testing time, as well as ongoing monitoring to ensure that it is coming up with the right answers.
In this post, we will share how you can use multi-Region as an architectural approach to achieve higher resilience on Amazon Web Services (AWS). This approach relies on first operating a workload across multiple Availability Zones within an AWS Region, before expanding to achieve even higher resilience by using multiple Regions. This is because within a Region there are multiple Availability Zones, which are physically separated by many miles but still close enough together (60 miles or less) to allow for single-digit millisecond latency. Each Availability Zone features one or more data centers, each housed in its own facility with its own redundant networking, connectivity, and power. Availability Zones provide fundamental building blocks that can help you achieve your resilience goals for your applications. First, you can benefit from the separation between Availability Zones by using Zonal services to specify which Availability Zone a resource is in, such as an Amazon Elastic Compute Cloud (Amazon EC2) instance. This means that if you build your application with redundant replicas of your application resources in each Availability Zone, you can gain excellent resilience to infrastructure events impacting any one Availability Zone.
A multi-Region approach is a reliable way to achieve a bounded recovery time for critical applications in the rare event of a service failure in a Region that is impacting your application. Each Region has strict logical and physical separation from other Regions. This purposeful design helps avoid service and infrastructure disruptions in one Region affecting another Region. This unique property of Regions can be used to build multi-Region applications with predictable fault domains.
While a multi-Region approach can improve your application’s resilience to failures, it can be challenging to build and operate such an application. It requires careful work to take advantage of the isolation between Regions, with care taken to not remove this isolation benefit at the application level. For example, if you fail over an application between Regions, you need to maintain strict separation between your application stacks in each Region, be aware of all the application dependencies, and fail over all parts of the application together. This kind of system requires planning and coordination amongst many engineering and business teams, especially with a complex, microservices-based architecture that could have several dependencies between applications.
If you’re replicating data between Regions using an asynchronous approach, you should be aware of the risk that not all your data has been replicated to the standby Region when you fail over. Because there’s a finite time needed to copy data over between Regions, data might be out of sync between the primary and standby Regions. If you use a synchronously replicated database across Regions to support your applications running from more than one Region concurrently, you avoid issues with data being out of sync when starting your application in the new Region. However, this introduces higher latency characteristics into your application’s resources. This is because writes need to commit to more than one Region, and the Regions can span hundreds or thousands of miles from one another. This latency characteristic needs to be accounted for in your application design. In addition, synchronous replication can increase the chance for correlated failures because writes need to be committed to more than one Region to be successful. If there is an impairment within one Region, you’ll need to form a quorum for writes to be successful, which typically involves having your database in three Regions and having a quorum of two out of three.
Finally, you need to practice the failover and simulate Region impairments to know that it works when you need it. It’s a substantial time and resource investment to regularly rotate your application between Regions to practice failover, but it’s a recommended practice if you plan to build a multi-Region application.
Given these additional considerations when implementing a multi-Region approach, for most AWS customers, multi-AZ is the right approach for building and operating resiliently in the cloud. This approach helps mitigate most infrastructure failures, which are usually contained within an Availability Zone. A multi-Region approach is most common in the following scenarios.
Meet regulatory and compliance requirements and enhance disaster recovery capabilities
Regulated industries like financial services and healthcare and life sciences can require that applications be multi-Region. Healthcare providers and pharmaceutical companies, for example, often deploy electronic health records (EHR), clinical trial management systems, and other applications across multiple Regions for enhanced data redundancy, disaster recovery, and compliance with regional data privacy regulations (like HIPAA in the US or GDPR in the EU). Epic on AWS, for example, is typically deployed across multiple Availability Zones and multiple Regions to increase the resilience of customers’ EHR and integrated application environment, making full use of the resources and geographic diversity of the AWS Cloud.
Banks and financial institutions, including Fidelity and Vanguard, also deploy many of their core trading and investment platforms and customer-facing applications across multiple Regions for enhanced business continuity and compliance with local data protection regulations.
Achieve a bounded recovery time to support highly available business-critical workloads
With growing demand for always-on applications and services, companies are increasingly reliant on cloud-based services and infrastructure for day-to-day operations and business continuity. While a single Region supports highly available and resilient applications, distributing workloads across multiple Regions enables a bounded recovery time in the rare event of a disruption to the application. The physical and logical separation of Regions provides a well-defined fault isolation boundary that you can use to create predictable fault boundaries for your applications. If their application experiences issues in one Region, the workloads can continue operating in another Region, which minimizes downtime for customers and users.
Streaming platforms like Netflix, NBCUniversal, and Disney, for example, deploy their content delivery networks (CDNs) and video streaming infrastructure across multiple Regions to provide a seamless media experience for their customers. In many cases, video streaming and video gaming companies deploy their infrastructure across multiple Regions to offer lower-latency gaming experiences for players worldwide.
Automotive companies such as Honda deploy their connected vehicle platforms across multiple Regions to scale globally. They use geo-location routing that identifies the closest broker the vehicle should communicate with based on customer-configured rules that govern how vehicles connect to the cloud infrastructure. This allows them to reliably connect millions of vehicles to the cloud while supporting high availability.
Conclusion
No matter the industry or scenario, AWS is the definitive choice for organizations that want to build and run highly available, resilient applications in the cloud, with resilience built into its infrastructure, operational models, and comprehensive capabilities across Regions. To learn how to choose between the different options for building resilience into your application, see the Well-Architected reliability pillar, and for a detailed framework for choosing multi-Region, see AWS Multi-Region Fundamentals.
The computer mouse is a wonderful invention, but for the past few
months I’ve been working to use mine as little as possible for
productivity and ergonomic reasons. It should not be surprising that
there are quite a few open-source applications, utilities, and
configuration options that are either designed to or incidentally
assist in creating a keyboard-driven desktop. This includes tiling window
management with PaperWM, the Vimium browser extension, Input Remapper, and more.
The Vox Pupuli project has
announced the first release of OpenVox, a
“soft-fork” of the Puppet
automation framework. The intention to fork was announced
in December 2024.
OpenVox 8.11 is functionally equivalent to Puppet and should be a
drop-in replacement. Be aware, of course, that even though you can
type the same commands, use all the same modules and extensions, and
configure the same settings, OpenVox is not yet tested to the same
standard that Puppet is. […]
Please don’t use these packages on critical production
infrastructures yet, unless you’re comfortable with troubleshooting
and reporting back on the silly errors we’ve made while rebranding and
rebuilding.
Version
10.0 of the Wine Windows compatibility layer is out. “This release
represents a year of development effort and over 6,000 individual
changes“. Those changes include full support for the Arm64EC
architecture, better high-DPI display support, Wayland enabled by default,
and more.
Artificial intelligence (AI) is writing law today. This has required no changes in legislative procedure or the rules of legislative bodies—all it takes is one legislator, or legislative assistant, to use generative AI in the process of drafting a bill.
In fact, the use of AI by legislators is only likely to become more prevalent. There are currently projects in the US House, US Senate, and legislatures around the world to trial the use of AI in various ways: searching databases, drafting text, summarizing meetings, performing policy research and analysis, and more. A Brazilian municipality passed the first known AI-written law in 2023.
That’s not surprising; AI is being used more everywhere. What is coming into focus is how policymakers will use AI and, critically, how this use will change the balance of power between the legislative and executive branches of government. Soon, US legislators may turn to AI to help them keep pace with the increasing complexity of their lawmaking—and this will suppress the power and discretion of the executive branch to make policy.
Demand for Increasingly Complex Legislation
Legislators are writing increasingly long, intricate, and complicated laws that human legislative drafters have trouble producing. Already in the US, the multibillion-dollar lobbying industry is subsidizing lawmakers in writing baroque laws: suggesting paragraphs to add to bills, specifying benefits for some, carving out exceptions for others. Indeed, the lobbying industry is growing in complexity and influence worldwide.
Several years ago, researchers studied bills introduced into state legislatures throughout the US, looking at which bills were wholly original texts and which borrowed text from other states or from lobbyist-written model legislation. Their conclusion was not very surprising. Those who borrowed the most text were in legislatures that were less resourced. This makes sense: If you’re a part-time legislator, perhaps unpaid and without a lot of staff, you need to rely on more external support to draft legislation. When the scope of policymaking outstrips the resources of legislators, they look for help. Today, that often means lobbyists, who provide expertise, research services, and drafting labor to legislators at the local, state, and federal levels at no charge. Of course, they are not unbiased: They seek to exert influence on behalf of their clients.
Another study, at the US federal level, measured the complexity of policies proposed in legislation and tried to determine the factors that led to such growing complexity. While there are numerous ways to measure legal complexity, these authors focused on the specificity of institutional design: How exacting is Congress in laying out the relational network of branches, agencies, and officials that will share power to implement the policy?
In looking at bills enacted between 1993 and 2014, the researchers found two things. First, they concluded that ideological polarization drives complexity. The suggestion is that if a legislator is on the extreme end of the ideological spectrum, they’re more likely to introduce a complex law that constrains the discretion of, as the authors put it, “entrenched bureaucratic interests.” And second, they found that divided government drives complexity to a large degree: Significant legislation passed under divided government was found to be 65 percent more complex than similar legislation passed under unified government. Their conclusion is that, if a legislator’s party controls Congress, and the opposing party controls the White House, the legislator will want to give the executive as little wiggle room as possible. When legislators’ preferences disagree with the executive’s, the legislature is incentivized to write laws that specify all the details. This gives the agency designated to implement the law as little discretion as possible.
Because polarization and divided government are increasingly entrenched in the US, the demand for complex legislation at the federal level is likely to grow. Today, we have both the greatest ideological polarization in Congress in living memory and an increasingly divided government at the federal level. Between 1900 and 1970 (57th through 90th Congresses), we had 27 instances of unified government and only seven divided; nearly a four-to-one ratio. Since then, the trend is roughly the opposite. As of the start of the next Congress, we will have had 20 divided governments and only eight unified (nearly a three-to-one ratio). And while the incoming Trump administration will see a unified government, the extremely closely divided House may often make this Congress look and feel like a divided one (see the recent government shutdown crisis as an exemplar) and makes truly divided government a strong possibility in 2027.
Another related factor driving the complexity of legislation is the need to do it all at once. The lobbyist feeding frenzy—spurring major bills like the Affordable Care Act to be thousands of pages in length—is driven in part by gridlock in Congress. Congressional productivity has dropped so low that bills on any given policy issue seem like a once-in-a-generation opportunity for legislators—and lobbyists—to set policy.
These dynamics also impact the states. States often have divided governments, albeit less often than they used to, and their demand for drafting assistance is arguably higher due to their significantly smaller staffs. And since the productivity of Congress has cratered in recent years, significantly more policymaking is happening at the state level.
But there’s another reason, particular to the US federal government, that will likely force congressional legislation to be more complex even during unified government. In June 2024, the US Supreme Court overturned the Chevron doctrine, which gave executive agencies broad power to specify and implement legislation. Suddenly, there is a mandate from the Supreme Court for more specific legislation. Issues that have historically been left implicitly to the executive branch are now required to be either explicitly delegated to agencies or specified directly in statute. Either way, the Court’s ruling implied that law should become more complex and that Congress should increase its policymaking capacity.
This affects the balance of power between the executive and legislative branches of government. When the legislature delegates less to the executive branch, it increases its own power. Every decision made explicitly in statute is a decision the executive makes not on its own but, rather, according to the directive of the legislature. In the US system of separation of powers, administrative law is a tool for balancing power among the legislative, executive, and judicial branches. The legislature gets to decide when to delegate and when not to, and it can respond to judicial review to adjust its delegation of control as needed. The elimination of Chevron will induce the legislature to exert its control over delegation more robustly.
At the same time, there are powerful political incentives for Congress to be vague and to rely on someone else, like agency bureaucrats, to make hard decisions. That empowers third parties—the corporations, or lobbyists—that have been gifted by the overturning of Chevron a new tool in arguing against administrative regulations not specifically backed up by law. A continuing stream of Supreme Court decisions handing victories to unpopular industries could be another driver of complex law, adding political pressure to pass legislative fixes.
AI Can Supply Complex Legislation
Congress may or may not be up to the challenge of putting more policy details into law, but the external forces outlined above—lobbyists, the judiciary, and an increasingly divided and polarized government—are pushing them to do so. When Congress does take on the task of writing complex legislation, it’s quite likely it will turn to AI for help.
Two particular AI capabilities enable Congress to write laws different from laws humans tend to write. One, AI models have an enormous scope of expertise, whereas people have only a handful of specializations. Large language models (LLMs) like the one powering ChatGPT can generate legislative text on funding specialty crop harvesting mechanization equally as well as material on energy efficiency standards for street lighting. This enables a legislator to address more topics simultaneously. Two, AI models have the sophistication to work with a higher degree of complexity than people can. Modern LLM systems can instantaneously perform several simultaneous multistep reasoning tasks using information from thousands of pages of documents. This enables a legislator to fill in more baroque detail on any given topic.
That’s not to say that handing over legislative drafting to machines is easily done. Modernizing any institutional process is extremely hard, even when the technology is readily available and performant. And modern AI still has a ways to go to achieve mastery of complex legal and policy issues. But the basic tools are there.
AI can be used in each step of lawmaking, and this will bring various benefits to policymakers. It could let them work on more policies—more bills—at the same time, add more detail and specificity to each bill, or interpret and incorporate more feedback from constituents and outside groups. The addition of a single AI tool to a legislative office may have an impact similar to adding several people to their staff, but with far lower cost.
Speed sometimes matters when writing law. When there is a change of governing party, there is often a rush to change as much policy as possible to match the platform of the new regime. AI could help legislators do that kind of wholesale revision. The result could be policy that is more responsive to voters—or more political instability. Already in 2024, the US House’s Office of the Clerk has begun using AI to speed up the process of producing cost estimates for bills and understanding how new legislation relates to existing code. Ohio has used an AI tool to do wholesale revision of state administrative law since 2020.
AI can also make laws clearer and more consistent. With their superhuman attention spans, AI tools are good at enforcing syntactic and grammatical rules. They will be effective at drafting text in precise and proper legislative language, or offering detailed feedback to human drafters. Borrowing ideas from software development, where coders use tools to identify common instances of bad programming practices, an AI reviewer can highlight bad law-writing practices. For example, it can detect when significant phrasing is inconsistent across a long bill. If a bill about insurance repeatedly lists a variety of disaster categories, but leaves one out one time, AI can catch that.
Perhaps this seems like minutiae, but a small ambiguity or mistake in law can have massive consequences. In 2015, the Affordable Care Act came close to being struck down because of a typo in four words, imperiling health care services extended to more than 7 million Americans.
There’s more that AI can do in the legislative process. AI can summarize bills and answer questions about their provisions. It can highlight aspects of a bill that align with, or are contrary to, different political points of view. We can even imagine a future in which AI can be used to simulate a new law and determine whether or not it would be effective, or what the side effects would be. This means that beyond writing them, AI could help lawmakers understand laws. Congress is notorious for producing bills hundreds of pages long, and many other countries sometimes have similarly massive omnibus bills that address many issues at once. It’s impossible for any one person to understand how each of these bills’ provisions would work. Many legislatures employ human analysis in budget or fiscal offices that analyze these bills and offer reports. AI could do this kind of work at greater speed and scale, so legislators could easily query an AI tool about how a particular bill would affect their district or areas of concern.
These capabilities will be attractive to legislators who are looking to expand their power and capabilities but don’t necessarily have more funding to hire human staff. We should understand the idea of AI-augmented lawmaking contextualized within the longer history of legislative technologies. To serve society at modern scales, we’ve had to come a long way from the Athenian ideals of direct democracy and sortition. Democracy no longer involves just one person and one vote to decide a policy. It involves hundreds of thousands of constituents electing one representative, who is augmented by a staff as well as subsidized by lobbyists, and who implements policy through a vast administrative state coordinated by digital technologies. Using AI to help those representatives specify and refine their policy ideas is part of a long history of transformation.
Whether all this AI augmentation is good for all of us subject to the laws they make is less clear. There are real risks to AI-written law, but those risks are not dramatically different from what we endure today. AI-written law trying to optimize for certain policy outcomes may get it wrong (just as many human-written laws are misguided). AI-written law may be manipulated to benefit one constituency over others, by the tech companies that develop the AI, or by the legislators who apply it, just as human lobbyists steer policy to benefit their clients.
Regardless of what anyone thinks of any of this, regardless of whether it will be a net positive or a net negative, AI-made legislation is coming—the growing complexity of policy demands it. It doesn’t require any changes in legislative procedures or agreement from any rules committee. All it takes is for one legislative assistant, or lobbyist, to fire up a chatbot and ask it to create a draft. When legislators voted on that Brazilian bill in 2023, they didn’t know it was AI-written; the use of ChatGPT was undisclosed. And even if they had known, it’s not clear it would have made a difference. In the future, as in the past, we won’t always know which laws will have good impacts and which will have bad effects, regardless of the words on the page, or who (or what) wrote them.
This essay was written with Nathan E. Sanders, and originally appeared in Lawfare.
Избирането на Доналд Тръмп за втори път за президент на САЩ не е добра новина за феминизма. Непосредствено след обявяването на резултатите от вота сред видни и невидни антифеминисти настана еуфория. Един от тях – тръмпистът с неонацистки уклон Никълъс (Ник) Фуентес, публикува в Хлаконичен пост: „Твоето тяло – мой избор. Завинаги.“
Заигравката на Фуентес е с известния феминистки лозунг в защита на правото на аборт „Моето тяло – мой избор“, но може да се отнесе към всякакви дейности, свързани с женското тяло, с които жените могат да бъдат несъгласни. Като насилието – сексуално или физическо.
Впрочем скоро след въпросния пост на Ник Фуентес му беше повдигнато обвинение за физическо насилие над жена. Жената е отишла до дома му като форма на протест срещу споменатия пост. Той я напръскал с лютив спрей и счупил телефона ѝ. Така де, нейното тяло (и телефон) – негов избор.
Не само изявени антифеминисти в САЩ или ислямистки режими като тези в Афганистан и Иран третират жените като обекти. Това е възможно и в Западна Европа, където правата на жените уж са издигнати на пиедестал. А случаят на Жизел Пелико хвърля светлина върху ужасяващите размери на проблема.
Трудни за възприемане факти и числа
Ако сте учили френски като дете, вероятно помните старата песен за моста на Авиньон, на който се танцува в кръг. От няколко месеца насам този град в Провансалските Алпи е популярен и в друг контекст – в Авиньон се провежда делото за сексуалното насилие над понастоящем 72-годишната Жизел Пелико, основен виновник за което е съпругът ѝ (днес вече бивш) Доминик Пелико.
Жизел и Доминик Пелико са връстници и се женят на 21-годишна възраст. Имат двама сина и дъщеря. След пенсионирането си наемат къща с градина и басейн в провансалското село (или малко градче) Мазан и се преселват там. Именно в нея съпругът започва да кани мъже, които да изнасилват приспаната му жена, която е упоявал още от 2011 г., докато са живели в околностите на Париж.
До 2020 г. поне 72-ма мъже изнасилват Жизел Пелико най-малко 92 пъти, докато тя няма представа за това, защото е упоена. Мисли, че влошеното ѝ здраве е знак за деменция. Не знае, че е заразена и с венерически болести, тъй като мъжът ѝ не е изисквал от изнасилвачите да са с презерватив. Сред тях има и ХИВ-позитивен мъж, но поне той не я заразява.
Когато разбира какво ѝ е било причинявано, Жизел решава да излезе с името си. Защото, смята тя, срамът е за извършителите, не за нея. Така се превръща в съвременна икона на феминизма във Франция.
Сексуалното насилие върху Жизел Пелико е разкрито случайно, и то не от нея, а от органите на реда. След като Доминик Пелико е хванат да снима под полата на непозната жена в магазина, полицията иззема компютъра и флашпаметите му. И намира повече от 20 000 снимки и видеозаписи, направени без знанието на жертвите.
Освен упоената Жизел и непознати жени, Доминик тайно е заснемал и двете си снахи в банята. Намерени са също снимки на собствената му дъщеря, приспана и облечена в бельото на майка си. Записите с изнасилванията на жена му са скрупульозно датирани и надписани с имената на извършителите. Това помага на полицията да намери повечето и 51 от тях, включително Доминик Пелико, са дадени на съд и получават ефективни присъди. Съпругът е осъден на 20 години затвор, останалите 50 мъже – на между 3 и 15 години.
Плашещи мащаби
При подобни драстични случаи на насилие общественото мнение е склонно да заклеймява извършителите като чудовища. Обявяването им за не-хора отвлича вниманието от нездравата тъкан на самото общество, която прави възможно съществуването на извършители на такива тежки престъпления.
Случаят на Жизел Пелико е показателен за мащабите на разпространеността на сексуалното насилие. Те са толкова големи, че не могат да се обяснят просто с лепването на етикета „чудовище“.
Съпругът е поканил поне 83 мъже да изнасилят жена му. От тях са се отзовали поне 72, което представлява близо 87% успеваемост на поканите. Вярно е, че комуникацията е протичала в чат канал, озаглавен „Без нейно знание“ (à son insu на френски), чиито потребители очевидно са били привлечени от идеята за сексуални действия с неподозиращи за това жени. Всички тези мъже обаче са живеели в радиус от едва шейсетина километра от дома на семейство Пелико в Мазан.
Изнасилвачите на Жизел са на възраст от 26 до 74 години, с различни степени на завършено образование и различни професии. Един от тях – 63-годишният Жан-Пиер Марешал – станал нещо като ученик на Доминик, започнал да упоява собствената си жена и на свой ред поканил „учителя“ си да я изнасили.
Малко вероятно е да има особена концентрация на сексуални насилници в точно определен район на Прованс. По-скоро и на други места е така, но голяма част от случаите на насилие остават неразкрити. Впрочем основателят на вече несъществуващия сайт Coco, част от който е бил чат каналът „Без нейно знание“, също е осъден, след като става ясно, че платформата му е била използвана от хора в цяла Франция, отговорни за над 23 000 престъпления, между които не само сексуално насилие, а педофилия и дори убийства.
Случаи от съседна Германия
Проблемът съвсем не е ограничен само във Франция. Лекар в германския град Билефелд например години наред упоявал и изнасилвал десетки свои пациентки. Когато го хванали, се самоубил в ареста.
Често сексуалното насилие остава неразкрито не само когато жертвите са упоени. Стигмата и трудността на доказването в съда разколебават много от преживелите насилие да търсят справедливост. Особено в малките населени места, където липсват ресурси за подкрепа.
Документална поредица на германската медийна група WDR проследява борбата за справедливост на три изнасилени жени (част 1 и част 2, на немски език). Една от тях е Зилке. Тя и мъжът ѝ се преселват от града на село, защото искат да живеят в сплотена общност. И я намират – в селото стават част от задружна приятелска компания. Осъществената мечта обаче се превръща в кошмар, когато един от приятелите изнасилва Зилке. Понеже тя си търси правата в съда, а мъжът ѝ я подкрепя, останалите от групата ги изолират – развалили са им хубавата компания. На отхвърлената двойка не ѝ остава друго, освен да продаде къщата и да напусне селото.
Много жертви на сексуално насилие обаче нямат възможност лесно да напуснат общностите, които ги подлагат на натиск. И просто се примиряват.
Баналността на сексуалното насилие
В известното си произведение „Айхман в Йерусалим. Репортаж за баналността на злото“ Хана Аренд защитава тезата, че много от нацистките функционери са пращали човешки същества на смърт не защото са някакви страшни злодеи, а понеже… са спазвали правилата. Те са оправдавали масовите убийства с това, че просто са изпълнявали заповеди. Така трябваше, такъв беше законът.
Нещо подобно лъха от оправданията на много от изнасилвачите на Жизел Пелико. Докато някои от тях, включително Доминик, признават, че са били наясно, че извършват насилие, други твърдят, че не са знаели. Казват, че щом съпругът е бил съгласен, те са си мислили, че това важи и за жена му – че за нея е форма на сексуална игра да бъде упоена и непознати мъже да правят секс с нея.
Да оставим настрана факта, че тези мъже са стигнали до Жизел чрез чат канала „Без нейно знание“, тоест са имали сериозно основание да предположат, че тя не е наясно какво ѝ се причинява. По-важното е, че на нито един от тях не му е хрумнало да я попита. Съгласието на мъжа ѝ им е било напълно достатъчно, за да смятат, че имат право да вършат с тялото ѝ каквото си искат.
Този случай отново поставя на дневен ред дебата във Франция за дефиницията за изнасилване, защото понастоящем тя не включва необходимостта от съгласие. Докато в много страни, включително в България, липсата на съгласие е част от определението за изнасилване, във Франция то представлява „всеки акт на сексуално проникване от какъвто и да е вид или орално-генитален акт, извършен чрез насилие, принуда, заплаха или изненада“.
За нормализацията на сексуалното насилие от гледна точка на извършителите вероятно има значение и фактът, че част от тях, включително Доминик Пелико, са преживели такова като деца. Това отваря сериозната тема за сексуалното насилие върху мъже. И все пак голямата част от извършителите на сексуално насилие са мъже, а мнозинството от потърпевшите са жени.
Отвличане на вниманието с изобретяване на външни врагове
Едно от най-силните послания на ксенофобската реторика е, че чужденците поради различната си култура могат да посегнат на „нашите жени“. Такива страхове се разпространяват в Европа по отношение на бежанците от ислямски страни, а в САЩ – основно спрямо идващите от Южна Америка, Централна Америка и Карибския басейн, особено ако са и чернокожи. По време на предизборната кампания Тръмп заплашваше, че ако Камала Харис спечели, Америка ще бъде залята от „безкраен поток нелегални пришълци изнасилвачи“.
Друга група, представяна като опасност за женското съсловие, особено в САЩ, са транс жените. Те според трансфобите си сменят пола основно с цел да тормозят „истинските“ жени в дамските тоалетни и съблекални.
Така на Сара Макбрайд, единствената транс жена в Конгреса на САЩ, се забранява да използва дамската тоалетна в Конгреса. За забраната особен принос има друга конгресменка – републиканката Нанси Мейс, – чиято активност е насочена основно в защита на „биологичните жени“ от „мъже с пениси“ в тоалетните и съблекалните, където те са „най-уязвими“.
В The Daily Showкомедиантката Дези Лайдик иронично отбелязва, че ако Мейс действително искаше да защити жените от сексуалните насилници, тя трябваше да се насочи към най-високите нива на новата власт, които принадлежат на собствената ѝ партия. Включително към президента Доналд Тръмп, който сам се хвали, че на модни ревюта влиза зад кулисите при преобличащите се манекенки.
Известно е и изказването на Тръмп, че понеже е известен, може да си позволява всичко с жените, включително да ги хваща за интимните части. Техните тела – негов избор.
Изглежда, не всички жени обаче са на това мнение. Срещу избрания за втори път президент има редица обвинения за сексуално насилие. В края на 2024 г. той беше осъден от федерален съд по едно от тях.
Случаите на Жизел Пелико, Зилке и на много други жени илюстрират факта, че обикновено опасността от сексуално насилие не идва от различните по етнос, цвят на кожата, религия или полова идентичност. Напротив, обикновено насилниците са част от близкото обкръжение – областта, града или селото, приятелската компания, дори най-близките хора в семейството.
Мъжете не са насилници по природа. Ако повече мъже упражняват насилие, то е, защото смятат, че могат да си го позволят. Защото това е урок, който се предава през поколенията.
С победата на Тръмп реториката за търсене на външни врагове ще се засилва, като същевременно с това по-често срещаните случаи на сексуално насилие – извършените от членове на собствената общност – ще се омаловажават. В тази ситуация на нарастващ популизъм историята на Жизел Пелико има отрезвяващо въздействие. Стига да бъде чута.
As our lives become increasingly intertwined with AI-powered tools and systems, it’s more important than ever to equip young people with the skills and knowledge they need to engage with AI safely and responsibly. AI literacy isn’t just about understanding the technology — it’s about fostering critical conversations on how to integrate AI tools into our lives while minimising potential harm — otherwise known as ‘AI safety’.
The UK AI Safety Institute defines AI safety as: “The understanding, prevention, and mitigation of harms from AI. These harms could be deliberate or accidental; caused to individuals, groups, organisations, nations or globally; and of many types, including but not limited to physical, psychological, social, or economic harms.”
As a result of this growing need, we’re thrilled to announce the latest addition to our AI literacy programme, Experience AI — ‘AI safety: responsibility, privacy, and security’. Co-developed with Google DeepMind, this comprehensive suite of free resources is designed to empower 11- to 14-year-olds to understand and address the challenges of AI technologies. Whether you’re a teacher, youth leader, or parent, these resources provide everything you need to start the conversation.
Linking old and new topics
AI technologies are providing huge benefits to society, but as they become more prevalent we cannot ignore the challenges AI tools bring with them. Many of the challenges aren’t new, such as concerns over data privacy or misinformation, but AI systems have the potential to amplify these issues.
Our resources use familiar online safety themes — like data privacy and media literacy — and apply AI concepts to start the conversation about how AI systems might change the way we approach our digital lives.
Each session explores a specific area:
Your data and AI: How data-driven AI systems use data differently to traditional software and why that changes data privacy concerns
Media literacy in the age of AI: The ease of creating believable, AI-generated content and the importance of verifying information
Using AI tools responsibly: Encouraging critical thinking about how AI is marketed and understanding personal and developer responsibilities
Each topic is designed to engage young people to consider both their own interactions with AI systems and the ethical responsibilities of developers.
Designed to be flexible
Our AI safety resources have flexibility and ease of delivery at their core, and each session is built around three key components:
Animations: Each session begins with a concise, engaging video introducing the key AI concept using sound pedagogy — making it easy to deliver and effective. The video then links the AI concept to the online safety topic and opens threads for thought and conversation, which the learners explore through the rest of the activities.
Unplugged activities: These hands-on, screen-free activities — ranging from role-playing games to thought-provoking challenges — allow learners to engage directly with the topics.
Discussion questions: Tailored for various settings, these questions help spark meaningful conversations in classrooms, clubs, or at home.
Experience AI has always been about allowing everyone — including those without a technical background or specialism in computer science — to deliver high-quality AI learning experiences, which is why we often use videos to support conceptual learning.
In addition, we want these sessions to be impactful in many different contexts, so we included unplugged activities so that you don’t need a computer room to run them! There is also advice on shortening the activities or splitting them so you can deliver them over two sessions if you want.
The discussion topics provide a time-efficient way of exploring some key implications with learners, which we think will be more effective in smaller groups or more informal settings. They also highlight topics that we feel are important but may not be appropriate for every learner, for example, the rise of inappropriate deepfake images, which you might discuss with a 14-year-old but not an 11-year-old.
A modular approach for all contexts
Our previous resources have all followed a format suitable for delivery in a classroom, but for these resources, we wanted to widen the potential contexts in which they could be used. Instead of prescribing the exact order to deliver them, educators are encouraged to mix and match activities that they feel would be effective for their context.
We hope this will empower anyone, no matter their surroundings, to have meaningful conversations about AI safety with young people.
The modular design ensures maximum flexibility. For example:
A teacher might combine the video with an unplugged activity and follow-up discussion for a 60-minute lesson
A club leader could show the video and run a quick activity in a 30-minute session
A parent might watch the video and use the discussion questions during dinner to explore how generative AI shapes the content their children encounter
The importance of AI safety education
With AI becoming a larger part of daily life, young people need the tools to think critically about its use. From understanding how their data is used to spotting misinformation, these resources are designed to build confidence and critical thinking in an AI-powered world.
AI safety is about empowering young people to be informed consumers of AI tools. By using these resources, you’ll help the next generation not only navigate AI, but shape its future. Dive into our materials, start a conversation, and inspire young minds to think critically about the role of AI in their lives.
Ready to get started? Explore our AI safety resources today: rpf.io/aisafetyblog. Together, we can empower every child to thrive in a digital world.
Since its inception, Let’s Encrypt has been sending expiration notification emails to subscribers that have provided an email address to us. We will be ending this service on June 4, 2025. The decision to end this service is the result of the following factors:
Over the past 10 years more and more of our subscribers have been able to put reliable automation into place for certificate renewal.
Providing expiration notification emails means that we have to retain millions of email addresses connected to issuance records. As an organization that values privacy, removing this requirement is important to us.
Providing expiration notifications costs Let’s Encrypt tens of thousands of dollars per year, money that we believe can be better spent on other aspects of our infrastructure.
Providing expiration notifications adds complexity to our infrastructure, which takes time and attention to manage and increases the likelihood of mistakes being made. Over the long term, particularly as we add support for new service components, we need to manage overall complexity by phasing out system components that can no longer be justified.
For those who would like to continue receiving expiration notifications, we recommend using a third party service such as Red Sift Certificates Lite (formerly Hardenize). Red Sift’s monitoring service providing expiration emails is free of charge for up to 250 certificates. More monitoring options can be found here.
While we will be minimizing the email addresses we retain connected to issuance data, you can opt in to receive other emails. We’ll keep you informed about technical updates, and other news about Let’s Encrypt and our parent nonprofit, ISRG, based on the preferences you choose. You can sign up for our email lists below:
To provide the best experiences, we use technologies like cookies to store and/or access device information. Consenting to these technologies will allow us to process data such as browsing behavior or unique IDs on this site. Not consenting or withdrawing consent, may adversely affect certain features and functions.
Functional
Always active
The technical storage or access is strictly necessary for the legitimate purpose of enabling the use of a specific service explicitly requested by the subscriber or user, or for the sole purpose of carrying out the transmission of a communication over an electronic communications network.
Preferences
The technical storage or access is necessary for the legitimate purpose of storing preferences that are not requested by the subscriber or user.
Statistics
The technical storage or access that is used exclusively for statistical purposes.The technical storage or access that is used exclusively for anonymous statistical purposes. Without a subpoena, voluntary compliance on the part of your Internet Service Provider, or additional records from a third party, information stored or retrieved for this purpose alone cannot usually be used to identify you.
Marketing
The technical storage or access is required to create user profiles to send advertising, or to track the user on a website or across several websites for similar marketing purposes.