Sr. Content Developer at Microsoft, working remotely in PA, TechBash conference organizer, former Microsoft MVP, Husband, Dad and Geek.
151438 stories
·
33 followers

Cursor continues acquisition Spree with Graphite deal

1 Share
Graphite is an AI code review assistant that was last valued at $290 million.
Read the whole story
alvinashcraft
9 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

The DOJ's Jeffrey Epstein Files Are Here

1 Share
Forced by an act of Congress, the Justice Department has released “hundreds of thousands” of pages of documents related to Epstein—but not everything, as is required by law.
Read the whole story
alvinashcraft
9 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Fast Focus on the Data Landscape

1 Share
From: VisualStudio
Duration: 21:31
Views: 32

In this recorded Fast Focus Live! 360 session with Buck Woody, you’ll learn a practical way to cut through data tool overload by starting with the problem—not the technology. Buck shows how to classify workloads, separate transactional needs from analytics and AI, and make platform choices that align with real business value.

You’ll also learn a simple set of filters to evaluate options and a lightweight decision loop you can use to keep your data architecture adaptable as your environment changes.

🔑 What You’ll Learn
• How to recognize the “data paradox”: too many tools, not enough clarity
• The difference between strategy and tactics for data and analytics projects
• How to classify workloads into three pillars: Online transition Processing (OLTP), advanced analytics, and AI
• Why transactional workloads and reporting/analytics should almost never share the same system
• When to use batch vs. streaming ingestion and how “eventual” really is “good enough” for most reporting
• How AI workloads (training data, RAG, and models) change your storage and processing patterns
• A three-part filter for picking tools: value/ROI, skills & ecosystem, and data gravity & governance
• How to factor in operational overhead, support, and total cost of ownership—not just license price
• How to use the OODA loop (Observe–Orient–Decide–Act) to iterate on architecture

⏱️ Chapters
00:00 The data paradox: tool sprawl, process chaos, and misused tech
03:32 Strategy vs. tactics: starting with goals, not tools
05:38 Process, Platform, People
06:25 From data platforms to workload solutions (problem-first thinking)
08:15 Workload Pillar 1: OLTP
13:29 Workload Pillar 2: Advanced analytics
12:20 Workload Pillar 3: AI
14:45 Filter #1: Value profile
16:23 Filter #2: Skill & maturity
16:38 Filter #3: Gravity & ecosystem
19:00 The OODA loop (Observe–Orient–Decide–Act) & final guidance

🔗 Links
• Explore more Live! 360 sessions: https://aka.ms/L360Orlando25
• Join us at out upcoming VS Live! events: https://aka.ms/VSLiveEvents

👤 Speaker: Buck Woody
Chief Data Officer, Straight Path Solutions

#dataarchitecture #dataengineering #AI

Read the whole story
alvinashcraft
9 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

What do people love about Rust?

1 Share

Rust has been named Stack Overflow's Most Loved (now called Most Admired) language every year since our 1.0 release in 2015. That means people who use Rust want to keep using Rust1--and not just for performance-heavy stuff or embedded development, but for shell scripts, web apps, and all kinds of things you wouldn't expect. One of our participants captured it well when they said, "At this point, I don't want to write code in any other language but Rust."

When we sat down to crunch the vision doc data, one of the things we really wanted to explain was: What is it that inspires that strong loyalty to Rust?2 Based on the interviews, the answer is at once simple and complicated. The short version is that Rust empowers them to write reliable and efficient software. If that sounds familiar, it should: it's the slogan that we have right there on our web page. The more interesting question is how that empowerment comes about, and what it implies for how we evolve Rust.

What do people appreciate about Rust?

The first thing we noticed is that, throughout every conversation, no matter whether someone is writing their first Rust program or has been using it for years, no matter whether they're building massive data clusters or embedded devices or just messing around, there are a consistent set of things that they say they like about Rust.

The first is reliability. People love that "if it compiles, it works" feeling:

"What I really love about Rust is that if it compiles it usually runs. That is fantastic, and that is something that I'm not used to in Java." -- Senior software engineer working in automotive embedded systems

"Rust is one of those languages that has just got your back. You will have a lot more sleep and you actually have to be less clever." -- Rust consultant and open source framework developer

Another, of course, is efficiency. This comes up in particular at the extremes, both very large scale (data centers) and very small scale (embedded):

"I want to keep the machine resources there for the [main] computation. Not stealing resources for a watchdog." -- Software engineer working on data science platforms

"You also get a speed benefit from using Rust. For example, [..] just the fact that we changed from this Python component to a Rust component gave us a 100fold speed increase." -- Rust developer at a medical device startup

Efficiency comes up particularly often when talking to customers running "at-scale" workloads, where even small performance wins can translate into big cost savings:

"We have a library -- effectively it's like an embedded database -- that we deploy on lots of machines. It was written in Java and we recently rewrote it from Java to Rust and we got close to I think 9x to 10x performance wins." -- Distinguished engineer working on cloud infrastructure services

"I'm seeing 4x efficiency in the same module between Java code that loads a VM and Rust. That's a lot of money you save in data center cost." -- Backend engineering company founder specializing in financial services

At the other end of the spectrum, people doing embedded development or working at low-levels of abstraction highlight Rust's ability to give low-level control and access to system details:

"Rust was that replacement for C I'd been looking for forever." -- Backend engineering company founder specializing in financial services

"If you're going to write something new and you do kind of low-level systemsy stuff, I think Rust is honestly the only real choice." -- Distinguished engineer

Many people cite the importance of Rust's supportive tooling, which helps them get up and going quickly, and in particular the compiler's error messages:

"I think a big part of why I was able to succeed at learning Rust is the tooling. For me, getting started with Rust, the language was challenging, but the tooling was incredibly easy." -- Executive at a developer tools company

"The tooling really works for me and works for us. The number one way that I think I engage with Rust is through its tooling ecosystem. I build my code through Cargo. I test it through Cargo. We rely on Clippy for everything." -- Embedded systems engineer working on safety-critical robotics

"I think the error messages and suggestions from the Rust compiler are super helpful also." -- Professor specializing in formal verification

Finally, one of Rust's most important virtues is its extensibility. Both in the language itself and through the crates.io ecosystem, Rust is designed to let end-users create libraries and abstractions that meet their needs:

"The crate ecosystem combined with the stability guarantees and the semantic versioning mean that it's the best grab and go ecosystem I've ever seen." -- Computer science professor and programming language designer

"I think proc macros are a really big superpower for Rust." -- Creator and maintainer of Rust networking libraries

"Rust is incredibly good at making it very very easy to get started, to reuse things, just to experiment quickly with new tools, new libraries, all the rest of it... so for me, as an experimentation platform, it's great." -- Rust expert and consultant focused on embedded and real-time systems

But what they love is the sense of empowerment and versatility

Reliability, efficiency, tooling, ecosystem—these are all things that people appreciate about Rust. But what they love isn't any one of those things. It's the way the combination makes Rust a trusted, versatile tool that you can bring to virtually any problem:

"When I got to know about it, I was like 'yeah this is the language I've been looking for'. This is the language that will just make me stop thinking about using C and Python. So I just have to use Rust because then I can go as low as possible as high as possible." -- Software engineer and community organizer in Africa

"I wanted a language that works well from top to bottom in a stacking all the way from embedded to very fancy applications" -- Computer science professor and programming language designer

"If [Rust] is going to try and sort of sell itself more in any particular way, I would probably be saying high performance, highly expressive, general purpose language, with the great aspect that you can write everything from the top to the bottom of your stack in it." -- Rust expert and consultant focused on embedded and real-time systems

Each piece is necessary for the whole to work

Take away the reliability, and you don't trust it: you're second-guessing every deployment, afraid to refactor, hesitant to let junior developers touch the critical paths.

"Rust just lowers that bar. It's a lot easier to write correct Rust code. As a leader on the team, I feel a lot safer when we have less experienced engineers contributing to these critical applications." -- Distinguished engineer working on cloud infrastructure services

"My experience with writing Rust software tends to be once you've got it working, it stays working. That's a combination of a lot of care taken in terms of backwards compatibility with the language and a lot of care taken around the general ecosystem." -- Rust expert and consultant focused on embedded and real-time systems

Reliability also provides guardrails that help people enter new domains—whether you're a beginner learning the ropes or an expert venturing into unfamiliar territory:

"Rust introduces you to all these things, like match and all these really nice functional programming methods." -- Software engineer with production Rust experience

"I think Rust ownership discipline is useful both for regular Rust programmers and also for verification. I think it allows you to within the scope of your function to know very clearly what you're modifying, what's not being modified, what's aliased and what's not aliased." -- Professor specializing in formal verification

"I discovered Rust... and was basically using it just to give myself a little bit more confidence being like a solo firmware developer" -- Software engineer working on automotive digital cockpit systems

Take away the efficiency and low-level control, and there are places you can't go: embedded systems, real-time applications, anywhere that cost-per-cycle matters.

"The performance in Rust is nutty. It is so much better and it's safe. When we rewrote C++ and C libraries or C applications into Rust, they would end up being faster because Rust was better at laying out memory." -- Senior Principal Engineer leading consumer shopping experiences

"9 times out of 10, I write microcontroller code and I only test it through unit testing. I put it on real hardware and it just works the first time." -- Embedded systems engineer working on safety-critical robotics

"I can confidently build systems that scale." -- Engineering manager with 20 years experience in media and streaming platforms

Take away the tooling and ecosystem, and you can't get started: or you can, but it's a slog, and you never feel productive.

"For me, getting started with Rust, the language was challenging, but the tooling was incredibly easy... I could just start writing code and it would build and run, and that to me made a huge difference." -- Founder and CEO of company creating developer tools

"Cargo is an amazing package manager. It is probably the best one I've ever worked with. I don't think I ever run into issues with Cargo. It just works." -- Software engineer with production Rust experience

"The Rust compiler is fantastic at kind of the errors it gives you. It's tremendously helpful in the type of errors it produces for it. But not just errors, but the fact it also catches the errors that other languages may not catch." -- Distinguished engineer working on cloud infrastructure services

The result: Rust as a gateway into new domains

When all these pieces come together, something interesting happens: Rust becomes a gateway into domains that would otherwise be inaccessible. We heard story after story of people whose careers changed because Rust gave them confidence to tackle things they couldn't before:

"I was civil engineering and I studied front-end development on my own, self taught. I had no computer background. I got interested in Rust and distributed systems and designs and systems around it. I changed my major, I studied CS and Rust at the same time." -- Software engineer transitioning to cryptography research

"I've been working with arbitrary subsidiaries of [a multinational engineering and technology company] for the last 25 years. Always doing software development mostly in the Java space... two years ago I started peeking into the automotive sector. In that context it was a natural consequence to either start working with C++ (which I did not want to do) or take the opportunity to dive into the newly established Rust ecosystem." -- Senior software engineer working in automotive embedded systems

"I started in blockchain. Currently I'm doing something else at my day job. Rust actually gave me the way to get into that domain." -- Rust developer and aerospace community leader

"Before that, I had 10 years of programming on some dynamic programming languages, especially Ruby, to develop web applications. I wanted to choose some language which focuses on system programming, so I chose Rust as my new choice. It is a change of my career." -- Rust consultant and author working in automotive systems and blockchain infrastructure

But the balance is crucial

Each of Rust's attributes are necessary for versatility across domains. But when taken too far, or when other attributes are missing, they can become an obstacle.

Example: Complex APIs and type complexity

One of the most powerful aspects of Rust is the way that its type system allows modeling aspects of the application domain. This prevents bugs and also makes it easier for noobs to get started3:

"Instead of using just a raw bit field, somebody encoded it into the type system. So when you'd have a function like 'open door', you can't pass an 'open door' if the door's already open. The type system will just kick that out and reject it." -- Software engineer working on automotive digital cockpit systems

"You can create contracts. For example, when you are allowed to use locks in which order." -- Senior embedded systems engineer working on automotive middleware development

The problem though is that sometimes the work to encode those invariants in types can create something that feels more complex than the problem itself:

"When you got Rust that's both async and generic and has lifetimes, then those types become so complicated that you basically have to be some sort of Rust god in order to even understand this code or be able to do it." -- Software engineer with production Rust experience

"Instead of spaghetti code, you have spaghetti typing" -- Platform architect at automotive semiconductor company

"I find it more opaque, harder to get my head around it. The types describe not just the interface of the thing but also the lifetime and how you are accessing it, whether it's on the stack or the heap, there's a lot of stuff packed into them." -- Software engineer working on data science platforms

This leads some to advocate for not using some of Rust's more complex features unless they are truly needed:

"My argument is that the hard parts of Rust -- traits, lifetimes, etc -- are not actually fundamental for being productive. There's a way to set up the learning curve and libraries to onboard people a lot faster." -- Creator and maintainer of Rust networking libraries

Example: Async ecosystem is performant but doesn't meet the bar for supportiveness

Async Rust has fueled a huge jump in using Rust to build network systems. But many commenters talked about the sense that "async Rust" was something altogether more difficult than sync Rust:

"I feel like there's a ramp in learning and then there's a jump and then there's async over here. And so the goal is to get enough excitement about Rust to where you can jump the chasm of sadness and land on the async Rust side." -- Software engineer working on automotive digital cockpit systems

"My general impression is actually pretty negative. It feels unbaked... there is a lot of arcane knowledge that you need in order to use it effectively, like Pin---like I could not tell you how Pin works, right?" -- Research software engineer with Rust expertise

For Rust to provide that "trusted tool that will help you tackle new domains" experience, people need to be leverage their expectations and knowledge of Rust in that new domain. With async, not only are there missing language features (e.g., async fn in traits only became available last year, and still have gaps), but the supportive tooling and ecosystem that users count on to "bridge the gap" elsewhere works less well:

"I was in favor of not using async, because the error messages were so hard to deal with." -- Desktop application developer

"The fact that there are still plenty of situations where you go that library looks useful, I want to use that library and then that immediately locks you into one of tokio-rs or one of the other runtimes, and you're like that's a bit disappointing because I was trying to write a library as well and now I'm locked into a runtime." -- Safety systems engineer working on functional safety for Linux

"We generally use Rust for services, and we use async a lot because a lot of libraries to interact with databases and other things are async. The times when we've had problems with this is like, um, unexplained high CPU usage, for example. The only really direct way to try to troubleshoot that or diagnose it is like, OK, I'm going to attach GDB and I'm gonna try to see what all of the threads are doing. GDB is -- I mean, this is not Rust's fault obviously -- but GDB is not a very easy to use tool, especially in a larger application. [..] And with async, it's, more difficult, because you don't see your code running, it's actually just sitting on the heap right now. Early on, I didn't actually realize that that was the case." -- Experienced Rust developer at a company using Rust and Python

Async is important enough that it merits a deep dive. Our research revealed a lot of frustration but we didn't go deep enough to give more specific insights. This would be a good task to be undertaken by the future User Research team (as proposed in our first post).

Example: The wealth of crates on crates.io are a key enabler but can be an obstacle

We mentioned earlier how Rust's extensibility is part of how it achieves versatility. Mechanisms like overloadable operators, traits, and macros let libraries create rich experiences for developers; a minimal standard library combined with easy package management encourage the creation of a rich ecosystem of crates covering needs both common and niche. However, particularly when people are first getting started, that extensibility can come at the cost of supportiveness, when the "tyranny of choice" becomes overwhelming:

"The crates to use are sort of undiscoverable. There's a layer of tacit knowledge about what crates to use for specific things that you kind of gather through experience and through difficulty. Everyone's doing all of their research." -- Web developer and conference speaker working on developer frameworks

"Crates.io gives you some of the metadata that you need to make those decisions, but it's not like a one stop shop, right? It's not like you go to crates.io and ask 'what I want to accomplish X, what library do I use'---it doesn't just answer that." -- Research software engineer

The Rust org has historically been reluctant to "bless" particular crates in the ecosystem. But the reality is that some crates are omnipresent. This is particular challenging for new users to navigate:

"The tutorial uses Result<Box<dyn Error>> -- but nobody else does. Everybody uses anyhow-result... I started off using the result thing but all the information I found has example code using anyhow. It was a bit of a mismatch and I didn't know what I should do." -- Software engineer working on data science platforms

"There is no clear recorded consensus on which 3P crates to use. [..] Sometimes it's really not clear---which CBOR crate do you use?[..] It's not easy to see which crates are still actively maintained. [..] The fact that there are so many crates on crates.io makes that a little bit of a risk." -- Rust team from a large technology company

Recommendations

Enumerate Rust's design goals and integrating them into our processes

We recommend creating an RFC that defines the goals we are shooting for as we work on Rust. The RFC should cover the experience of using Rust in total (language, tools, and libraries). This RFC could be authored by the proposed User Research team, though it's not clear who should accept it — perhaps the User Research team itself, or perhaps the leadership council.

This post identified how the real "empowering magic" of Rust arises from achieving a number of different attributes all at once -- reliability, efficiency, low-level control, supportiveness, and so forth. It would be valuable to have a canonical list of those values that we could collectively refer to as a community and that we could use when evaluating RFCs or other proposed designs.

There have been a number of prior approaches at this work that we could build on (e.g., this post from Tyler Mandry, the Rustacean Principles, or the Rust Design Axioms). One insight from our research is that we don't need to define which values are "most important". We've seen that for Rust to truly work, it must achieve all the factors at once. Instead of ranking, it may help to describe how it feels when you:

  • Don't achieve it (too little)
  • Get it right (the sweet spot)
  • Go overboard (too much)

This "goldilocks" framing helps people recognize where they are and course-correct, without creating false hierarchies.

Double down on extensibility

We recommend doubling down on extensibility as a core strategy. Rust's extensibility — traits, macros, operator overloading — has been key to its versatility. But that extensibility is currently concentrated in certain areas: the type system and early-stage proc macros. We should expand it to cover supportive interfaces (better diagnostics and guidance from crates) and compilation workflow (letting crates integrate at more stages of the build process).

Rust's extensibility is a big part of how Rust achieves versatility, and that versatility is a big part of what people love about Rust. Leveraging mechanisms like proc macros, the trait system, and the borrow checker, Rust crates are able to expose high-level, elegant interfaces that compile down to efficiemt machine code. At its best, it can feel a bit like magic.

Unfortunately, while Rust gives crates good tools for building safe, efficient abstractions, we don't provide tools to enable supportive ones. Within builtin Rust language concepts, we have worked hard to create effective error messages that help steer users to success; we ship the compiler with lints that catch common mistakes or enforce important conventions. But crates benefit from none of this. RFCs like RFC #3368, which introduced the diagnostic namespace and #[diagnostic::on_unimplemented], Rust has already begun moving in this direction. We should continue and look for opportunities to go further, particularly for proc-macros which often create DSL-like interfaces.

The other major challenge for extensibility is concerned with the build system and backend. Rust's current extensibility mechanisms (e.g., build.rs, proc-macros) are focused on the early stages of the compilation process. But many extensions to Rust, ranging from interop to theorem proving to GPU programming to distributed systems, would benefit from being able to integrate into other stages of the compilation process. The Stable MIR project and the build-std project goal are two examples of this sort of work.

Doubling down on extensibility will not only make current Rust easier to use, it will enable and support Rust's use in new domains. Safety Critical applications in particular require a host of custom lints and tooling to support the associated standards. Compiler extensibility allows Rust to support those niche needs in a more general way.

Help users get oriented in the Rust ecosystem

We recommend finding ways to help users navigate the crates.io ecosystem. Idiomatic Rust today relies on custom crates for everything from error-handling to async runtimes. Leaning on the ecosystem helps Rust to scale to more domains and allows for innovative new approaches to be discovered. But finding which crates to use presents a real obstacle when people are getting started. The Rust org maintains a carefully neutral stance, which is good, but also means that people don't have anywhere to go for advice on a good "starter set" crates.

The right solution here is not obvious. Expanding the standard library could cut off further experimentation; "blessing" crates carries risks of politics. But just because the right solution is difficult doesn't mean we should ignore the problem. Rust has a history of exploring creative solutions to old tradeoffs, and we should turn that energy to this problem as well.

Part of the solution is enabling better interop between libraries. This could come in the form of adding key interop traits (particularly for async) or by blessing standard building blocks (e.g., the http crate, which provides type definitions for HTTP libraries). Changes to coherence rules can also help, as the current rules do not permit a new interop trait to be introduced in the ecosystem and incrementally adopted.

Conclusion

To sum up the main points in this post:

  • What people love about Rust is the way it empowers them to tackle tough problems and new domains. This is not the result of any one attribute but rather a careful balancing act between many; if any of them are compromised, the language suffers significantly.
  • We make three recommendations to help Rust continue to scale across domains and usage levels
    • Enumerate and describe Rust's design goals and integrate them into our processes, helping to ensure they are observed by future language designers and the broader ecosystem.
    • Double down on extensibility, introducing the ability for crates to influence the develop experience and the compilation pipeline.
    • Help users to navigate the crates.io ecosystem and enable smoother interop
  1. In 2025, 72% of Rust users said they wanted to keep using it. In the past, Rust had a way higher score than any other language, but this year, Gleam came awfully close, with 70%! Good for them! Gleam looks awesome--and hey, good choice on the fn keyword. ;)

  2. And, uh, how can we be sure not to mess it up?

  3. ...for experienced devs operating on less sleep, who do tend to act a lot like noobs.

Read the whole story
alvinashcraft
10 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Vector Search in Oracle Database 26ai

1 Share

The use case: Help Me Learn My New Car

As much as folks are lamenting about the new cloud version of Oracle support, I have other issues on my mind- like trying to acclimate to my first electric vehicle, even though I already owned a gas-powered Mini Cooper. 

As I was looking for a good use case to test new vector search with Oracle 26ai, it occurred to me that I could use something better than a key word search when using the manual to my new car. 

What if I used the manual, which is public information and could be easily made searchable as my use case?

Imagine you run a support portal (internal or customer-facing) with lots of short “support notes”:

  • “My MINI won’t charge with a public CCS fast charger…”
  • “The app shows charging error after an OTA update…”
  • “My EV plug latch is stuck…”

You discover quickly that keyword search often fails because people describe the same problem in different words. Vector search solves this by comparing meaning, not exact terms.  I’ve been facing something similar as I try to come up to speed with my car, so I decided to see if AI could help me out.

So in this blog post, I will work on:

  1. store the user manual and its embedding vector in a table
  2. create an HNSW vector index for fast nearest-neighbor search
  3. run a query that returns the most semantically similar sections in the manual to stop having to search for the info and often, failing.

Oracle 26ai is a strong fit because it lets you do this inside the database with a native VECTOR type, SQL functions, and built-in vector indexing options.

Create Object, Load Data, ETC.

Assumptions

  • You already have embeddings (from your app / model pipeline), or
  • You’ll generate embeddings in-database via DBMS_VECTOR.UTL_TO_EMBEDDING using a model you’ve loaded (optional section below). Oracle Documentation

Dimension note: pick a dimension that matches your embedding model (e.g., 768, 1024, 1536, etc.).

Table to store notes and vectors

1) Drop & create a table for support notes + embeddings

begin

execute immediate 'drop table support_notes purge';
 exception
 when others then
   if sqlcode != -942 then raise; end if;
end;

/
create table support_notes (
note_id     number generated by default as identity primary key,
created_at  timestamp default systimestamp not null,
title       varchar2(200) not null,
body        clob not null,
-- VECTOR(d) is the native vector datatype (d = embedding dimension)
embedding   vector(1536) not null
);

Oracle’s native VECTOR datatype is designed for storing embeddings directly in tables, so this was surprisingly easy.

Insert sample data (I have two options)

Option A: Insert embeddings you already have

Below I show the “shape” of the insert. Replace the […] with real embedding values from your model pipeline.

Make sure to insert precomputed embeddings (example shape; replace with real vectors) when using this yourself:

insert into support_notes (title, body, embedding) values (
  'Fast charging fails at public station',
  'CCS fast charger starts then stops after 5-10 seconds. Happens on multiple stations.',
  vector('[0.0123, -0.0456, 0.0789, ...]')  -- 1536 floats
);
insert into support_notes (title, body, embedding) values (
'Charging error after software update',
'After an OTA update, the car reports a charging error intermittently, especially on Level 2.',
vector('[0.0011, -0.0234, 0.0567, ...]')
);

commit;

Option B (this is optional), generate embeddings in the database:

Oracle 26ai supports generating embeddings via DBMS_VECTOR.UTL_TO_EMBEDDING (using JSON params and an in-database model you’ve loaded).

This Assumes you already loaded an ONNX embedding model named ‘doc_model’.

var params clob;

exec :params := '{"provider":"database","model":"doc_model"}';

insert into support_notes (title, body, embedding)
values (
'EV plug latch stuck',
'The charging connector latch won’t release unless I unlock twice.',
dbms_vector.utl_to_embedding('The charging connector latch won’t release unless I unlock twice.', json(:params))
);

commit;

Create the vector index (HNSW)

For fast similarity search, create an HNSW index, i.e. we’ll create an HNSW vector index (in-memory neighbor graph):

create vector index support_notes_hnsw_idx
on support_notes (embedding)
organization inmemory neighbor graph
distance cosine
with target accuracy 90;

I discovered how to do this pattern for HNSW vector indexes in Oracle AI Vector Search in the following blog.

Run A Top-K Similar Vector Search

You provide a query vector and ask for the nearest neighbors by cosine distance.  The following query will find the five most similar notes in the manual as part of an input vector.  We’ll need to replace the :qvec with query embedding(VECTOR(1536)) and in a lot of apps, you can just compute this embedding in the app tier and then bind it.

select
 note_id,
 title,
 vector_distance(embedding, :qvec, cosine) as dist
from support_notes
order by dist
fetch first 5 rows only;

VECTOR_DISTANCE is one of the core vector SQL functions used for similarity search, so it makes this easy, too.

Why use Oracle for vector search?

  • One platform for OLTP + AI search: keep your transactional data, security model, and vector similarity search in the same database instead of bolting on a separate vector store. Oracle positions AI Vector Search specifically around native VECTOR storage + in-database generation options.
  • First-class indexing choices: Oracle supports multiple vector index types (including HNSW and others) and documents when to use them.
  • In-database embedding support: if you want, you can load an ONNX embedding model and generate embeddings with DBMS_VECTOR.
  • Hybrid search path: if you later want “keywords + meaning”, Oracle documents hybrid vector indexing that combines text and vector search in one approach.

Below is a single, run-it-in-SQLcl demo script for Oracle Database 26ai that does hybrid search (keyword + vector) over a realistic “2024 MINI Cooper SE user manual” use case.

  • Dimension: VECTOR(1536)
  • Distance: COSINE
  • Hybrid: Oracle Text (keyword) + Vector index (semantic)
  • Embeddings: generated in-db via DBMS_VECTOR.UTL_TO_EMBEDDING (you’ll plug in your model/provider)
-- mini_manual_hybrid_demo.sql
-- Hybrid search demo for Oracle 26ai: Oracle Text + Vector Search (COSINE, 1536 dims)
-- Use case: Chunked 2024 MINI Cooper SE manual content (simplify manual navigation)

set echo on
set feedback on
set pagesize 200
set linesize 200
set serveroutput on
whenever sqlerror exit sql.sqlcode

prompt =========================================================
prompt 0) Preconditions
prompt - You need an embedding model accessible to DBMS_VECTOR
prompt - Update the PARAMS JSON below to match environment
prompt =========================================================

--------------------------------------------------------------------------------
-- 1) Drop old objects (safe rerun)
--------------------------------------------------------------------------------
begin
  execute immediate 'drop table mini_manual_chunks purge';
exception when others then
  if sqlcode != -942 then raise; end if;
end;
/

begin
  execute immediate 'drop sequence mini_chunk_src_seq';
exception when others then
  if sqlcode != -2289 then raise; end if;
end;
/

--------------------------------------------------------------------------------
-- 2) Create table: manual chunks + metadata + embedding
--------------------------------------------------------------------------------
prompt =========================================================
prompt 1) Create storage table for chunked manual text + vectors
prompt =========================================================

create table mini_manual_chunks (
  chunk_id        number generated by default as identity primary key,
  source_id       number not null,
  doc_title       varchar2(200) not null,
  section_path    varchar2(500) not null,  -- e.g. "Charging > troubleshooting"
  page_hint       varchar2(50),
  chunk_text      clob not null,
  -- dimension is fixed at 1536 (match your embedding model)
  embedding       vector(1536) not null,
  created_at      timestamp default systimestamp not null
);

create sequence mini_chunk_src_seq start with 1000 increment by 1;

--------------------------------------------------------------------------------
-- 3) Helper: embedding params + convenience procedure to insert chunks
--------------------------------------------------------------------------------
prompt =========================================================
prompt 2) Setup embedding params + insert helper
prompt =========================================================

-- IMPORTANT: Update this JSON for environment.
--  - {"provider":"database","model":"MINI_MANUAL_EMBED_1536"}
--  - {"provider":"oci","credential_name":"OCI_CRED","endpoint":"...","model":"..."}
--  - {"provider":"openai","credential_name":"...","model":"text-embedding-3-large"}
--
-- Keep the dimension consistent with VECTOR(1536).
var EMBED_PARAMS clob
begin
  :EMBED_PARAMS := '{
    "provider": "database",
    "model": "MINI_MANUAL_EMBED_1536"
  }';
end;
/

create or replace procedure add_manual_chunk(
  p_source_id    in number,
  p_doc_title    in varchar2,
  p_section_path in varchar2,
  p_page_hint    in varchar2,
  p_chunk_text   in clob
) as
  v_emb vector(1536);
begin
  -- Generate embedding in-database
  v_emb := dbms_vector.utl_to_embedding(
             p_chunk_text,
             json(:EMBED_PARAMS)
           );

  insert into mini_manual_chunks(source_id, doc_title, section_path, page_hint, chunk_text, embedding)
  values (p_source_id, p_doc_title, p_section_path, p_page_hint, p_chunk_text, v_emb);
end;
/
show errors

--------------------------------------------------------------------------------
-- 4) Insert realistic sample manual chunks (MINI Cooper SE focused)
--    The ones I chose are short, “chunkable” blocks like you'd create after parsing the PDF.
--------------------------------------------------------------------------------
prompt =========================================================
prompt 3) Insert realistic MINI Cooper SE manual-style sample chunks
prompt =========================================================

declare
  v_src number := mini_chunk_src_seq.nextval;
begin
  add_manual_chunk(
    v_src,
    '2024 MINI Cooper SE Owner''s Manual' 
    'Charging > Overview',
    'p. 110',
    q'[
Charging your vehicle: You can charge using AC charging (Level 1/Level 2) or DC fast charging when equipped and when supported by the charging station.
Always follow the instructions on the charging station and ensure the connector is fully seated before leaving the vehicle.
If charging does not start, verify the vehicle is unlocked (if required), the connector is latched, and the station is authorized.
]'
  );

  add_manual_chunk(
    v_src,
    '2024 MINI Cooper SE Owner''s Manual',
    'Charging > AC charging > Tips',
    'p. 114',
    q'[
AC charging: Use a compatible charging cable and confirm the outlet or EVSE is operating properly.
If the charging cable has status indicators, check for fault lights. Avoid using extension cords unless explicitly permitted by the EVSE manufacturer.
Charging may be reduced or interrupted to protect the battery under extreme temperatures.
]'
  );

  add_manual_chunk(
    v_src,
    '2024 MINI Cooper SE Owner''s Manual',
    'Charging > DC fast charging > Troubleshooting',
    'p. 120',
    q'[
DC fast charging: If the charging session starts and then stops, try re-initiating the session and confirm the connector is fully engaged.
Some stations require re-authorization if the session is interrupted.
If repeated attempts fail, try a different stall or station. Inspect the connector for debris and ensure the charge port area is clear.
]'
  );

  add_manual_chunk(
    v_src,
    '2024 MINI Cooper SE Owner''s Manual',
    'Charging > Charge port & connector',
    'p. 112',
    q'[
Charge port: Keep the charge port and connector clean and dry. Do not insert objects into the charge port.
If the connector does not release, confirm the vehicle is unlocked and follow the recommended release procedure.
Do not force the connector; damage may occur.
]'
  );

  add_manual_chunk(
    v_src,
    '2024 MINI Cooper SE Owner''s Manual',
    'Driver assistance > Lighting > Headlights',
    'p. 68',
    q'[
Automatic headlight control: When set to the default position, the vehicle controls exterior lights based on ambient light conditions.
Daytime running lights may be active during daylight. In low-light conditions, the system turns on headlights and tail lamps automatically.
Driver remains responsible for using appropriate lighting in poor visibility.
]'
  );

  add_manual_chunk(
    v_src,
    '2024 MINI Cooper SE Owner''s Manual',
    'Infotainment > Mobile app > Charging status',
    'p. 142',
    q'[
Charging status in the mobile app: The app may show charging state, estimated completion time, and notifications.
If the app shows an error but the vehicle is charging, refresh the status or verify connectivity.
For persistent issues, confirm the vehicle services are active and the phone has network access.
]'
  );

  commit;
end;
/
prompt Insert complete.

--------------------------------------------------------------------------------
-- 5) Create HYBRID indexes:
--    a) Oracle Text index on chunk_text for keyword search
--    b) Vector index (HNSW) on embedding for semantic search using cosine distance
--------------------------------------------------------------------------------
prompt =========================================================
prompt 4) Create indexes for HYBRID search (Text + Vector)
prompt =========================================================

-- Oracle Text (keyword / BM25-style scoring with CONTAINS)
-- Note: CTXSYS must be installed/configured 
create index mini_manual_text_idx
on mini_manual_chunks(chunk_text)
indextype is ctxsys.context;

-- Vector index (HNSW) for cosine similarity
create vector index mini_manual_vec_idx
on mini_manual_chunks(embedding)
organization inmemory neighbor graph
distance cosine
with target accuracy 90;

--------------------------------------------------------------------------------
-- 6) Queries
--------------------------------------------------------------------------------
prompt =========================================================
prompt 5) DEMO: Pure keyword search (Oracle Text)
prompt =========================================================

-- Keyword query example: "connector does not release"
-- Score is available via SCORE(1)
select
  chunk_id,
  section_path,
  page_hint,
  score(1) as text_score,
  substr(chunk_text, 1, 160) as preview
from mini_manual_chunks
where contains(chunk_text, 'connector AND release', 1) > 0
order by text_score desc
fetch first 5 rows only;

prompt =========================================================
prompt 6) DEMO: Pure vector similarity search (semantic)
prompt =========================================================

-- Create a query embedding from a user question (in-db)
var Q_TEXT clob
var QVEC  vector(1536)

begin
  :Q_TEXT := 'My fast charging starts then stops after a few seconds. What should I check?';
  :QVEC   := dbms_vector.utl_to_embedding(:Q_TEXT, json(:EMBED_PARAMS));
end;
/

select
  chunk_id,
  section_path,
  page_hint,
  vector_distance(embedding, :QVEC, cosine) as dist,
  substr(chunk_text, 1, 160) as preview
from mini_manual_chunks
order by dist
fetch first 5 rows only;

prompt =========================================================
prompt 7) DEMO: HYBRID search (keyword + vector)
prompt =========================================================

-- Hybrid strategy:
--  1) Use keyword query to enforce topical relevance (CONTAINS)
--  2) Use vector distance to order by semantic similarity within that set

var KQ varchar2(4000)
begin
  :KQ := 'charging AND (fast OR DC OR station)';
end;
/

select
  chunk_id,
  section_path,
  page_hint,
  score(1) as text_score,
  vector_distance(embedding, :QVEC, cosine) as dist,
  substr(chunk_text, 1, 160) as preview
from mini_manual_chunks
where contains(chunk_text, :KQ, 1) > 0
order by dist
fetch first 5 rows only;

prompt =========================================================
prompt 8) DEMO: “Simplify the manual” output (a friendly answer-shaped result)
prompt =========================================================

-- In a real app you’d pass the top chunk(s) to your summarizer / RAG layer.
-- For demo, we return the best chunk as “what to do next”.

select
  'Suggested section: ' || section_path || ' (' || page_hint || ')' as suggestion,
  chunk_text as recommended_text
from (
  select section_path, page_hint, chunk_text,
         vector_distance(embedding, :QVEC, cosine) as dist
  from mini_manual_chunks
  where contains(chunk_text, :KQ, 1) > 0
  order by dist
)
fetch first 1 row only;

prompt =========================================================
prompt DONE.
prompt Next step: replace sample chunks with your parsed manual chunks.
prompt =========================================================

It took me a while to get this to work the way I wanted, had to view several examples, push some of the code through AI and I’m still fiddling with it, but it’s a start to making it easier for me to search the manual with simple text vs. keywords.

So, Does this Solve My “Simplify the Whole Manual” Goal?

I’m parsing the manual PDF into chunks (200–800 tokens-ish each), each with:

  1. section_path (table of contents path)
  2. page_hint (page or location marker)
  3. chunk_text (the actual chunk)
  4. Then generating embeddings (you can do it in the database, like the script, or in your app pipeline)
  5. Hybrid search:
    • Oracle Text: catches exact terms, model numbers, “DRL”, “CCS”, “release procedure”
    • Vector search: catches meaning (“starts then stops”, “interrupts after a few seconds”, “session fails”)
  6. The output:
    • Retrieve top 3–10 chunks
    • Summarize into “steps to try” + link to section/page

Example Query and Result Set

SQL> select
2 'Suggested section: ' || section_path || ' (' || page_hint || ')' as suggestion,
3 chunk_text as recommended_text
4 from (
5 select section_path, page_hint, chunk_text,
6 vector_distance(embedding, :QVEC, cosine) as dist
7 from mini_manual_chunks
8 where contains(chunk_text, :KQ, 1) > 0
9 order by dist
10 )
11 fetch first 1 row only;
SUGGESTION
Suggested section: Charging > DC fast charging > Troubleshooting (p. 120)


RECOMMENDED_TEXT

DC fast charging: If the charging session starts and then stops, try re-initiating the session and confirm the connector is fully engaged. Some stations require re-authorization if the session is interrupted. If repeated attempts fail, try a different stall or station. Inspect the connector for debris and ensure the charge port area is clear.

Why Oracle for this specific use case of manual simplification?

  • You get one system that can store: chunk text, metadata, vectors, and run both keyword + semantic search in SQL (less glue, fewer moving parts).
  • You can keep security and access control in the database (who can search which manuals / editions) if there was proprietary information which shouldn’t be assessable to the public.
  • You can run this close to your data and integrate it with your existing app patterns (APIs, SQL, PL/SQL), and scale it with indexes designed for the job (Oracle Text + HNSW).

I’ll revisit this as I keep coming up to speed with my new car.  I really knew my 2015 Mini Cooper JCW all the way down to the bolts and I’d like to understand my new 2024 Mini Cooper SE Resolute as well.  I’m hoping this will be a way to speed up that knowledge transfer.

Read the whole story
alvinashcraft
10 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Media3 1.9.0 - What’s new

1 Share
Posted by Kristina Simakova, Engineering Manager



Media3 1.9.0 – What's new?

Media3 1.9.0 is out! Besides the usual bug fixes and performance improvements, the latest release also contains four new or largely rewritten modules:
  • media3-inspector - Extract metadata and frames outside of playback

  • media3-ui-compose-material3 - Build a basic Material3 Compose Media UI in just a few steps

  • media3-cast - Automatically handle transitions between Cast and local playbacks

  • media3-decoder-av1 - Consistent AV1 playback with the rewritten extension decoder based on the dav1d library


We also added caching and memory management improvements to PreloadManager, and provided several new ExoPlayer, Transformer and MediaSession simplifications. 


This release also gives you the first experimental access to CompositionPlayer to preview media edits.  


Read on to find out more, and as always please check out the full release notes for a comprehensive overview of changes in this release.

Extract metadata and frames outside of playback

There are many cases where you want to inspect media without starting a playback. For example, you might want to detect which formats it contains or what its duration is, or to retrieve thumbnails.

The new media3-inspector module combines all utilities to inspect media without playback in one place:

  • MetadataRetriever to read duration, format and static metadata from a MediaItem.

  • FrameExtractor to get frames or thumbnails from an item. 

  • MediaExtractorCompat as a direct replacement for the Android platform MediaExtractor class, to get detailed information about samples in the file.


MetadataRetriever and FrameExtractor follow a simple AutoCloseable pattern. Have a look at our new guide pages for more details.

suspend fun extractThumbnail(mediaItem: MediaItem) {
  FrameExtractor.Builder(context, mediaItem).build().use {
    val thumbnail = frameExtractor.getThumbnail().await()
  } 
}

Build a basic Material3 Compose Media UI in just a few steps

In previous releases we started providing connector code between Compose UI elements and your Player instance. With Media3 1.9.0, we added a new module media3-ui-compose-material3 with fully-styled Material3 buttons and content elements. They allow you to build a media UI in just a few steps, while providing all the flexibility to customize style. If you prefer to build your own UI style, you can use the building blocks that take care of all the update and connection logic, so you only need to concentrate on designing the UI element. Please check out our extended guide pages for the Compose UI modules.

We are also still working on even more Compose components, like a prebuilt seek bar, a complete out-of-the-box replacement for PlayerView, as well as subtitle and ad integration.


@Composable
fun SimplePlayerUI(player: Player, modifier: Modifier = Modifier) {
  Column(modifier) {
    ContentFrame(player)  // Video surface and shutter logic
    Row (Modifier.align(Alignment.CenterHorizontally)) {                 
      SeekBackButton(player)   // Simple controls
      PlayPauseButton(player)
      SeekForwardButton(player)
    }
  }
}

Simple Compose player UI with out-of-the-box elements

Automatically handle transitions between Cast and local playbacks

The CastPlayer in the media3-cast module has been rewritten to automatically handle transitions between local playback (for example with ExoPlayer) and remote Cast playback.

When you set up your MediaSession, simply build a CastPlayer around your ExoPlayer and add a MediaRouteButton to your UI and you're done!


// MediaSession setup with CastPlayer 
val exoPlayer = ExoPlayer.Builder(context).build()
val castPlayer = CastPlayer.Builder(context).setLocalPlayer(exoPlayer).build()
val session = MediaSession.Builder(context, player)
// MediaRouteButton in UI 
@Composable fun UIWithMediaRouteButton() {
  MediaRouteButton()
}


New CastPlayer integration in Media3 session demo app


Consistent AV1 playback with the rewritten extension based on dav1d

The 1.9.0 release contains a completely rewritten AV1 extension module based on the popular dav1d library.

As with all extension decoder modules, please note that it requires building from source to bundle the relevant native code correctly. Bundling a decoder provides consistency and format support across all devices, but because it runs the decoding in your process, it's best suited for content you can trust. 

Integrate caching and memory management into PreloadManager

We made our PreloadManager even better as well. It already enabled you to preload media into memory outside of playback and then seamlessly hand it over to a player when needed. Although pretty performant, you still had to be careful to not exceed memory limits by accidentally preloading too much. So with Media3 1.9.0, we added two features that makes this a lot easier and more stable:


  1. Caching support – When defining how far to preload, you can now choose PreloadStatus.specifiedRangeCached(0, 5000) as a target state for preloaded items. This will add the specified range to your cache on disk instead of loading the data to memory. With this, you can provide a much larger range of items for preloading as the ones further away from the current item no longer need to occupy memory. Note that this requires setting a Cache in DefaultPreloadManager.Builder.

  2. Automatic memory management – We also updated our LoadControl interface to better handle the preload case so you are now able to set an explicit upper memory limit for all preloaded items in memory. It's 144 MB by default, and you can configure the limit in DefaultLoadControl.Builder. The DefaultPreloadManager will automatically stop preloading once the limit is reached, and automatically releases memory of lower priority items if required.

Rely on new simplified default behaviors in ExoPlayer

As always, we added lots of incremental improvements to ExoPlayer as well. To name just a few:
  • Mute and unmute – We already had a setVolume method, but have now added the convenience mute and unmute methods to easily restore the previous volume without keeping track of it yourself.

  • Stuck player detection – In some rare cases the player can get stuck in a buffering or playing state without making any progress, for example, due to codec issues or misconfigurations. Your users will be annoyed, but you never see these issues in your analytics! To make this more obvious, the player now reports a StuckPlayerException when it detects a stuck state.

  • Wakelock by default – The wake lock management was previously opt-in, resulting in hard to find edge cases where playback progress can be delayed a lot when running in the background. Now this feature is opt-out, so you don't have to worry about it and can also remove all manual wake lock handling around playback.

  • Simplified setting for CC button logic Changing TrackSelectionParameters to say "turn subtitles on/off" was surprisingly hard to get right, so we added a simple boolean selectTextByDefault option for this use case.

Simplify your media button preferences in MediaSession

Until now, defining your preferences for which buttons should show up in the media notification drawer on Android Auto or WearOS required defining custom commands and buttons, even if you simply wanted to trigger a standard player method.

Media3 1.9.0 has new functionality to make this a lot simpler – you can now define your media button preferences with a standard player command, requiring no custom command handling at all.


session.setMediaButtonPreferences(listOf(
    CommandButton.Builder(CommandButton.ICON_FAST_FORWARD) // choose an icon
      .setDisplayName(R.string.skip_forward)
      .setPlayerCommand(Player.COMMAND_SEEK_FORWARD) // choose an action 
      .build()
))

Media button preferences with fast forward button

CompositionPlayer for real-time preview

The 1.9.0 release introduces CompositionPlayer under a new @ExperimentalApi annotation. The annotation indicates that it is available for experimentation, but is still under development. 

CompositionPlayer is a new component in the Media3 editing APIs designed for real-time preview of media edits. Built upon the familiar Media3 Player interface, CompositionPlayer allows users to see their changes in action before committing to the export process. It uses the same Composition object that you would pass to Transformer for exporting, streamlining the editing workflow by unifying the data model for preview and export.

We encourage you to start using CompositionPlayer and share your feedback, and keep an eye out for forthcoming posts and updates to the documentation for more details.

InAppMuxer as a default muxer in Transformer

Transformer now uses InAppMp4Muxer as the default muxer for writing media container files. Internally, InAppMp4Muxer depends on the Media3 Muxer module, providing consistent behaviour across all API versions. 
Note that while Transformer no longer uses the Android platform's MediaMuxer by default, you can still provide FrameworkMuxer.Factory via setMuxerFactory if your use case requires it.

New speed adjustment APIs

The 1.9.0 release simplifies speed adjustments APIs for media editing. We've introduced new methods directly on EditedMediaItem.Builder to control speed, making the API more intuitive. You can now change the speed of a clip by calling setSpeed(SpeedProvider provider) on the EditedMediaItem.Builder:

val speedProvider = object : SpeedProvider {
    override fun getSpeed(presentationTimeUs: Long): Float {
        return speed
    }

    override fun getNextSpeedChangeTimeUs(timeUs: Long): Long {
        return C.TIME_UNSET
    }
}

EditedMediaItem speedEffectItem = EditedMediaItem.Builder(mediaItem)
    .setSpeed(speedProvider)
    .build()


This new approach replaces the previous method of using Effects#createExperimentalSpeedChangingEffects(), which we've deprecated and will remove in a future release.

Introducing track types for EditedMediaItemSequence

In the 1.9.0 release, EditedMediaItemSequence requires specifying desired output track types during sequence creation. This change ensures track handling is more explicit and robust across the entire Composition.

This is done via a new EditedMediaItemSequence.Builder constructor that accepts a set of track types (e.g., C.TRACK_TYPE_AUDIO, C.TRACK_TYPE_VIDEO). 

To simplify creation, we've added new static convenience methods:

  • EditedMediaItemSequence.withAudioFrom(List<EditedMediaItem>)

  • EditedMediaItemSequence.withVideoFrom(List<EditedMediaItem>)

  • EditedMediaItemSequence.withAudioAndVideoFrom(List<EditedMediaItem>)

We encourage you to migrate to the new constructor or the convenience methods for clearer and more reliable sequence definitions.

Example of creating a video-only sequence:

EditedMediaItemSequence videoOnlySequence =
    EditedMediaItemSequence.Builder(setOf(C.TRACK_TYPE_VIDEO))
        .addItem(editedMediaItem)
        .build()


---


Please get in touch via the Media3 issue Tracker if you run into any bugs, or if you have questions or feature requests. We look forward to hearing from you!
Read the whole story
alvinashcraft
11 minutes ago
reply
Pennsylvania, USA
Share this story
Delete
Next Page of Stories