<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Volodymyr Pavlyshyn</title>
    <description>The latest articles on DEV Community by Volodymyr Pavlyshyn (@volland).</description>
    <link>https://dev.to/volland</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F377537%2F203e8e29-233b-4230-9f97-a861ae4ad5b8.jpeg</url>
      <title>DEV Community: Volodymyr Pavlyshyn</title>
      <link>https://dev.to/volland</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/volland"/>
    <language>en</language>
    <item>
      <title>Pre and Post Filtering in Vector Search with Metadata and RAG Pipelines</title>
      <dc:creator>Volodymyr Pavlyshyn</dc:creator>
      <pubDate>Mon, 30 Sep 2024 14:50:05 +0000</pubDate>
      <link>https://dev.to/volland/pre-and-post-filtering-in-vector-search-with-metadata-and-rag-pipelines-2hji</link>
      <guid>https://dev.to/volland/pre-and-post-filtering-in-vector-search-with-metadata-and-rag-pipelines-2hji</guid>
      <description>&lt;p&gt;In the modern world of AI, managing vast amounts of data while keeping it relevant and accessible is a significant challenge, mainly when dealing with large language models (LLMs) and vector databases. One approach that has gained prominence in recent years is integrating vector search with metadata, especially in retrieval-augmented generation (RAG) pipelines. Vector search and metadata enable faster and more accurate data retrieval. However, the process of pre- and post-search filtering results plays a crucial role in ensuring data relevance.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Vector Search and Metadata Challenge
&lt;/h2&gt;

&lt;p&gt;In a typical vector search, you create embeddings from chunks of text, such as a PDF document. These embeddings allow the system to search for similar items and retrieve them based on relevance. The challenge, however, arises when you need to combine vector search results with structured metadata. For example, you may have timestamped text-based content and want to retrieve the most relevant content within a specific date range. This is where metadata becomes critical in refining search results.&lt;/p&gt;

&lt;p&gt;Unfortunately, most vector databases treat metadata as a secondary feature, isolating it from the primary vector search process. As a result, handling queries that combine vectors and metadata can become a challenge, particularly when the search needs to account for a dynamic range of filters, such as dates or other structured data.&lt;/p&gt;

&lt;h2&gt;
  
  
  LibSQL and vector search metadata
&lt;/h2&gt;

&lt;p&gt;LibSQL is a more general-purpose SQLite-based database that adds vector capabilities to regular data. Vectors are presented as blob columns of regular tables. It makes vector embeddings and metadata a first-class citizen that naturally builds deep integration of these data points.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  create table if not exists conversation (
    id varchar(36) primary key not null,
    startDate real,
    endDate real,
    summary text,
    vectorSummary F32_BLOB(512)
   );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It solves the challenge of metadata and vector search and eliminates impedance between vector data and regular structured data points in the same storage.&lt;/p&gt;

&lt;p&gt;As you can see, you can access vector-like data and start date in the same query.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;select c.id ,c.startDate, c.endDate, c.summary, vector_distance_cos(c.vectorSummary, vector(${vector})) distance
      from conversation
      where
      ${startDate ? `and c.startDate &amp;gt;= ${startDate.getTime()}` : ''}
      ${endDate ? `and c.endDate &amp;lt;= ${endDate.getTime()}` : ''}
      ${distance ? `and distance &amp;lt;= ${distance}` : ''}
      order by distance
      limit ${top};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;vector_distance_cos&lt;/strong&gt; calculated as distance allows us to make a primitive vector search that does a full scan and calculates distances on rows. We could optimize it with CTE and limit search and distance calculations to a much smaller subset of data.&lt;/p&gt;

&lt;p&gt;This approach could be calculation intensive and fail on large amounts of data.&lt;/p&gt;

&lt;p&gt;Libsql offers a way more effective vector search based on FlashDiskANN vector indexed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vector_top_k('idx_conversation_vectorSummary', ${vector} , ${top}) i
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;vector_top_k&lt;/strong&gt; is a table function that searches for the top of the newly created vector search index. As you can see, we could use only vector as a function parameter, and other columns could be used outside of the table function. So, to use a vector index together with different columns, we need to apply some strategies.&lt;/p&gt;

&lt;p&gt;Now we get a classical problem of integration vector search results with metadata queries.&lt;/p&gt;

&lt;h2&gt;
  
  
  Post-Filtering: A Common Approach
&lt;/h2&gt;

&lt;p&gt;The most widely adopted method in these pipelines is &lt;strong&gt;post-filtering&lt;/strong&gt;. In this approach, the system first retrieves data based on vector similarities and then applies metadata filters. For example, imagine you’re conducting a vector search to retrieve conversations relevant to a specific question. Still, you also want to ensure these conversations occurred in the past week.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgma4m3hwvav6x5ypufz0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgma4m3hwvav6x5ypufz0.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post-filtering allows the system to retrieve the most relevant vector-based results and subsequently filter out any that don’t meet the metadata criteria, such as date range. This method is efficient when vector similarity is the primary factor driving the search, and metadata is only applied as a secondary filter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    const sqlQuery = `
      select c.id ,c.startDate, c.endDate, c.summary, vector_distance_cos(c.vectorSummary, vector(${vector})) distance
      from  vector_top_k('idx_conversation_vectorSummary', ${vector} , ${top}) i
      inner join conversation c on i.id = c.rowid
      where 
      ${startDate ? `and c.startDate &amp;gt;= ${startDate.getTime()}` : ''}
      ${endDate ? `and c.endDate &amp;lt;= ${endDate.getTime()}` : ''}
      ${distance ? `and distance &amp;lt;= ${distance}` : ''}
      order by distance
      limit ${top};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, there are some limitations. For example, the initial vector search may yield fewer results or omit some relevant data before applying the metadata filter. If the search window is narrow enough, this can lead to complete results.&lt;/p&gt;

&lt;p&gt;One working strategy is to make the top value in vector_top_K much bigger. Be careful, though, as the function's default max number of results is around 200 rows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pre-Filtering: A More Complex Approach
&lt;/h2&gt;

&lt;p&gt;Pre-filtering is a more intricate approach but can be more effective in some instances. In pre-filtering, metadata is used as the primary filter before vector search takes place. This means that only data that meets the metadata criteria is passed into the vector search process, limiting the scope of the search right from the beginning.&lt;/p&gt;

&lt;p&gt;While this approach can significantly reduce the amount of irrelevant data in the final results, it comes with its own challenges. For example, pre-filtering requires a deeper understanding of the data structure and may necessitate denormalizing the data or creating separate pre-filtered tables. This can be resource-intensive and, in some cases, impractical for dynamic metadata like date ranges.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo0eqa75mcr71gel0gwjj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo0eqa75mcr71gel0gwjj.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In certain use cases, pre-filtering might outperform post-filtering. For instance, when the metadata (e.g., specific date ranges) is the most important filter, pre-filtering ensures the search is conducted only on the most relevant data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pre-filtering with distance-based filtering
&lt;/h2&gt;

&lt;p&gt;So, we are getting back to an old concept. We do prefiltering instead of using a vector index.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WITH FilteredDates AS (
    SELECT 
        c.id, 
        c.startDate, 
        c.endDate, 
        c.summary, 
        c.vectorSummary
    FROM 
        YourTable c
    WHERE 
        ${startDate ? `AND c.startDate &amp;gt;= ${startDate.getTime()}` : ''}
        ${endDate ? `AND c.endDate &amp;lt;= ${endDate.getTime()}` : ''}
),
DistanceCalculation AS (
    SELECT 
        fd.id, 
        fd.startDate, 
        fd.endDate, 
        fd.summary, 
        fd.vectorSummary,
        vector_distance_cos(fd.vectorSummary, vector(${vector})) AS distance
    FROM 
        FilteredDates fd
)
SELECT 
    dc.id, 
    dc.startDate, 
    dc.endDate, 
    dc.summary, 
    dc.distance
FROM 
    DistanceCalculation dc
WHERE 
    1=1
    ${distance ? `AND dc.distance &amp;lt;= ${distance}` : ''}
ORDER BY 
    dc.distance
LIMIT ${top};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It makes sense if the filter produces small data and distance calculation happens on the smaller data set.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2e6imnyo5g8qa32vov0r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2e6imnyo5g8qa32vov0r.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As a pro of this approach, you have full control over the data and get all results without omitting some typical values for extensive index searches.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing Between Pre and Post-Filtering
&lt;/h2&gt;

&lt;p&gt;Both pre-filtering and post-filtering have their advantages and disadvantages. Post-filtering is more accessible to implement, especially when vector similarity is the primary search factor, but it can lead to incomplete results. Pre-filtering, on the other hand, can yield more accurate results but requires more complex data handling and optimization.&lt;/p&gt;

&lt;p&gt;In practice, many systems combine both strategies, depending on the query. For example, they might start with a broad pre-filtering based on metadata (like date ranges) and then apply a more targeted vector search with post-filtering to refine the results further.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Vector search with metadata filtering offers a powerful approach for handling large-scale data retrieval in LLMs and RAG pipelines. Whether you choose pre-filtering or post-filtering—or a combination of both—depends on your application's specific requirements. As vector databases continue to evolve, future innovations that combine these two approaches more seamlessly will help improve data relevance and retrieval efficiency further.&lt;/p&gt;

</description>
      <category>rag</category>
      <category>vectorsearch</category>
      <category>libsql</category>
    </item>
    <item>
      <title>Personal Knowledge Graphs in AI RAG on user phone</title>
      <dc:creator>Volodymyr Pavlyshyn</dc:creator>
      <pubDate>Mon, 30 Sep 2024 14:46:58 +0000</pubDate>
      <link>https://dev.to/volland/personal-knowledge-graphs-in-ai-rag-on-user-phone-kj7</link>
      <guid>https://dev.to/volland/personal-knowledge-graphs-in-ai-rag-on-user-phone-kj7</guid>
      <description>&lt;p&gt;Graphs and vector search are potent tandems for AI-powered applications, which are booming nowadays. Personal knowledge graphs are the core of semantic memory for many agentic AI applications.&lt;/p&gt;

&lt;p&gt;At Mykin, we craft AI agentic architecture with a complex memory model directly on the user's device.&lt;/p&gt;

&lt;p&gt;Mykin is a privacy-focused AI agent on top of sovereign data owned by users.&lt;/p&gt;

&lt;p&gt;Kin. A personal AI for your work life&lt;br&gt;
Get inspired, talk things through, navigate situations or get personalized guidance with Kin. Built for privacy…&lt;br&gt;
mykin.ai&lt;/p&gt;

&lt;h2&gt;
  
  
  Our Nord Stars
&lt;/h2&gt;

&lt;p&gt;The technical Nord stars of mykin are :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Privacy by design — guide on how to keep architecture secure and private&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ssi principles — focus on user data ownership and sovereignty&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;local first architecture — give the instrument to the user to own &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Data Ownership
&lt;/h2&gt;

&lt;p&gt;All these Nord stars have one aspect in common—data ownership. The user has full control and ownership of the data. This means that we shift from a classical all-in-cloud centralized model to a local-first architecture where data is stored and processed, a mesh of user devices, and potentially some cloud services or capabilities are involved.&lt;/p&gt;

&lt;p&gt;So we need to run complex RAG and vector search and vector graph clustering primarily on user device.&lt;/p&gt;

&lt;h2&gt;
  
  
  Expectations for database capabilities
&lt;/h2&gt;

&lt;p&gt;general queries on structured data (regular application data) like messages, conversations, settings, etc&lt;br&gt;
vector search and similarity search capabilities to RAG pipelines and different LLM and ML-powered flows&lt;br&gt;
Graph and graph search capabilities (ML and semantic memory )&lt;br&gt;
As far as we work on mobile, we have a few tech capabilities, too&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;embeddable with good support for mobile bindings&lt;/li&gt;
&lt;li&gt;single file database that simplifies a backup&lt;/li&gt;
&lt;li&gt;portable&lt;/li&gt;
&lt;li&gt;battery friendly&lt;/li&gt;
&lt;li&gt;fast and nonblocking io as much as possible&lt;/li&gt;
&lt;li&gt;wide community support&lt;/li&gt;
&lt;li&gt;reliability
## LibSQL
If you follow my articles, you already know the answer — LibSQL&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I described the full journey of vector search and graphs on top of relational models in my articles&lt;/p&gt;

&lt;p&gt;Personal Knowledge Graphs in AI RAG-powered Applications with libSQL&lt;br&gt;
I spend a long time working on privacy first personal ai assistant&lt;br&gt;
ai.plainenglish.io&lt;/p&gt;

&lt;p&gt;We have 1 question — how to run LibSQL on a user device?&lt;/p&gt;

&lt;p&gt;We are using React Native, so the library should have react native bindings&lt;/p&gt;

&lt;p&gt;LibSQL on React native&lt;br&gt;
It is plenty of libraries for React native that run Sqlite but not LibSQL&lt;/p&gt;

&lt;p&gt;react-native-sqlite-storage&lt;/p&gt;

&lt;p&gt;Widely used with support for transactions and raw SQL queries.&lt;br&gt;
Supports both Android and iOS.&lt;br&gt;
Provides a promise-based API.&lt;br&gt;
react-native-sqlite-2&lt;/p&gt;

&lt;p&gt;A lightweight alternative.&lt;br&gt;
Based on a WebSQL API.&lt;br&gt;
Works well for simple databases but has limited features compared to react-native-sqlite-storage.&lt;br&gt;
react-native-sqlite&lt;/p&gt;

&lt;p&gt;Similar to react-native-sqlite-storage, but with more minimalistic features.&lt;br&gt;
Might require manual linking.&lt;br&gt;
watermelondb&lt;/p&gt;

&lt;p&gt;Built on top of SQLite but offers a more modern approach.&lt;br&gt;
Designed for highly scalable databases in React Native.&lt;br&gt;
Provides an ORM-like interface and works with large datasets efficiently.&lt;br&gt;
expo-sqlite (if using Expo)&lt;/p&gt;

&lt;p&gt;Built-in SQLite support for Expo apps.&lt;br&gt;
It is lightweight and easy to use but has fewer advanced features than other libraries.&lt;br&gt;
Expo-sqlite is now a de facto library for SQLite in the Expo ecosystem, and my first idea was to convince the community to add libsql as an engine or fork it and use it for our internal needs.&lt;/p&gt;

&lt;p&gt;It was much more challenging than I expected. Sometimes, a big open-source project is a closed door for new ideas and improvements. So it is a door that is hard to nook.&lt;/p&gt;

&lt;p&gt;OP-SQLite&lt;br&gt;
OP SQLite Documentation | Notion&lt;br&gt;
Built with Notion, the all-in-one connected workspace with publishing capabilities.&lt;br&gt;
ospfranco.notion.site&lt;/p&gt;

&lt;p&gt;The fastest SQLite library for react-native by Ospfranco is what I read the first time when I found OP-SQL in Git Hub. And it is&lt;/p&gt;

&lt;p&gt;It has few interesting features for react native app&lt;/p&gt;

&lt;p&gt;Async operations&lt;br&gt;
The default query runs synchronously on the JS thread. There are async versions for some of the operations. This will offload the SQLite processing to a different thread and prevent UI blocking. It is also real multi-concurrency, so it won’t bog down the event loop.&lt;/p&gt;

&lt;p&gt;Raw execution&lt;br&gt;
If you don’t care about the keys you can use a simplified execution that will return an array of results.&lt;/p&gt;

&lt;p&gt;Hooks&lt;br&gt;
You can subscribe to changes in your database by using an update hook that give a full row :&lt;/p&gt;

&lt;p&gt;// Bear in mind: rowId is not your table primary key but the internal rowId sqlite uses&lt;br&gt;
// to keep track of the table rows&lt;br&gt;
db.updateHook(({ rowId, table, operation, row = {} }) =&amp;gt; {&lt;br&gt;
  console.warn(&lt;code&gt;Hook has been called, rowId: ${rowId}, ${table}, ${operation}&lt;/code&gt;);&lt;br&gt;
  // Will contain the entire row that changed&lt;br&gt;
  // only on UPDATE and INSERT operations&lt;br&gt;
  console.warn(JSON.stringify(row, null, 2));&lt;br&gt;
});&lt;/p&gt;

&lt;p&gt;db.execute('INSERT INTO "User" (id, name, age, networth) VALUES(?, ?, ?, ?)', [&lt;br&gt;
  id,&lt;br&gt;
  name,&lt;br&gt;
  age,&lt;br&gt;
  networth,&lt;br&gt;
]);&lt;br&gt;
Extension Load&lt;br&gt;
It was the first library that allowed me to load an extension by myself and even more. Oskar adds CR-SQL extension as an option to a library to make it work out of the box !!!&lt;/p&gt;

&lt;p&gt;Open to Cooperation&lt;br&gt;
One of LibSQL's mottos is to be open to contributions. Oskar was more open to contributions, saw the amazing benefits of libsql, and added it as an option to op-sql.&lt;/p&gt;

&lt;p&gt;Little How-To&lt;br&gt;
So, how do you build a vector search-aware personal knowledge graph on a user device ?&lt;/p&gt;

&lt;p&gt;I expect that you will have a React native or expo project. You need to add op-sql&lt;/p&gt;

&lt;p&gt;yarn add @op-engineering/op-sqlite&lt;br&gt;
You need version 7.3.0+&lt;/p&gt;

&lt;p&gt;Now let's configure Libsql. You need to add this section to your package.json&lt;/p&gt;

&lt;p&gt;"op-sqlite": {&lt;br&gt;
    "libsql": true&lt;br&gt;
  }&lt;br&gt;
As far as we do a polymorphic library that runs not only on the device but on nodejs also. I made an abstraction that allows me to swap libsql implementations.&lt;/p&gt;

&lt;p&gt;// @ts-nocheck&lt;br&gt;
import {&lt;br&gt;
  open as openLibsql,&lt;br&gt;
  OPSQLiteConnection,&lt;br&gt;
  QueryResult,&lt;br&gt;
  Transaction,&lt;br&gt;
} from '@op-engineering/op-sqlite';&lt;br&gt;
import {&lt;br&gt;
  BatchQueryOptions,&lt;br&gt;
  DataQuery,&lt;br&gt;
  DataQueryResult,&lt;br&gt;
  IDataStore,&lt;br&gt;
  UpdateCallbackParams,&lt;br&gt;
  StoreOptions,&lt;br&gt;
} from '@mykin-ai/kin-core';&lt;br&gt;
import { documentDirectory } from 'expo-file-system';&lt;/p&gt;

&lt;p&gt;export class DataStoreService implements IDataStore {&lt;br&gt;
  private _db: OPSQLiteConnection | undefined;&lt;/p&gt;

&lt;p&gt;private _isOpen = false;&lt;/p&gt;

&lt;p&gt;public _name: string;&lt;br&gt;
  private _location: string;&lt;br&gt;
  public useCrSql = true;&lt;br&gt;
  private _options: StoreOptions;&lt;/p&gt;

&lt;p&gt;constructor(&lt;br&gt;
    name = ':memory:',&lt;br&gt;
    location = documentDirectory,&lt;br&gt;
    options: StoreOptions = {&lt;br&gt;
      vectorDimension: 512,&lt;br&gt;
      vectorType: 'F32',&lt;br&gt;
      vectorNeighborsCompression: 'float8',&lt;br&gt;
      vectorMaxNeighbors: 20,&lt;br&gt;
      dataAutoSync: false,&lt;br&gt;
      failOnErrors: false,&lt;br&gt;
      reportErrors: true,&lt;br&gt;
    },&lt;br&gt;
  ) {&lt;br&gt;
    this._name = name;&lt;br&gt;
    this._options = options;&lt;br&gt;
    if (location?.startsWith('file://')) {&lt;br&gt;
      this._location = location.split('file://')[1];&lt;br&gt;
    } else {&lt;br&gt;
      this._location = location;&lt;br&gt;
    }&lt;br&gt;
    if (this._location.endsWith('/')) {&lt;br&gt;
      this._location = this._location.slice(0, -1);&lt;br&gt;
    }&lt;br&gt;
  }&lt;/p&gt;

&lt;p&gt;getVectorOption() {&lt;br&gt;
    return {&lt;br&gt;
      dimension: this._options.vectorDimension,&lt;br&gt;
      type: this._options.vectorType,&lt;br&gt;
      compression: this._options.vectorNeighborsCompression,&lt;br&gt;
      maxNeighbors: this._options.vectorMaxNeighbors,&lt;br&gt;
    };&lt;br&gt;
  }&lt;/p&gt;

&lt;p&gt;async query(query: string, params?: any[] | undefined): Promise {&lt;br&gt;
    try {&lt;br&gt;
      await this.open(this._name);&lt;br&gt;
      const paramsWithCorrectTypes = params?.map((param) =&amp;gt; {&lt;br&gt;
        if (param === undefined || param === null) {&lt;br&gt;
          return null;&lt;br&gt;
        }&lt;br&gt;
        if (param === true) {&lt;br&gt;
          return 1;&lt;br&gt;
        }&lt;br&gt;
        if (param === false) {&lt;br&gt;
          return 0;&lt;br&gt;
        }&lt;br&gt;
        return param;&lt;br&gt;
      });&lt;br&gt;
      const data = await this._db.executeRawAsync(query, paramsWithCorrectTypes);&lt;br&gt;
      return {&lt;br&gt;
        isOk: true,&lt;br&gt;
        data,&lt;br&gt;
      };&lt;br&gt;
    } catch (e) {&lt;br&gt;
      console.error(e.code, e.message);&lt;br&gt;
      return {&lt;br&gt;
        isOk: false,&lt;br&gt;
        data: [],&lt;br&gt;
        errorCode: e.code || 'N/A',&lt;br&gt;
        error: e.message,&lt;br&gt;
      };&lt;br&gt;
    }&lt;br&gt;
  }&lt;/p&gt;

&lt;p&gt;async execute(query: string, params?: any[] | undefined): Promise {&lt;br&gt;
    try {&lt;br&gt;
      await this.open(this._name);&lt;br&gt;
      const paramsWithCorrectTypes = params?.map((param) =&amp;gt; {&lt;br&gt;
        if (param === undefined || param === null) {&lt;br&gt;
          return null;&lt;br&gt;
        }&lt;br&gt;
        if (param === true) {&lt;br&gt;
          return 1;&lt;br&gt;
        }&lt;br&gt;
        if (param === false) {&lt;br&gt;
          return 0;&lt;br&gt;
        }&lt;br&gt;
        return param;&lt;br&gt;
      });&lt;br&gt;
      const data = await this._db.executeAsync(query, paramsWithCorrectTypes);&lt;br&gt;
      return {&lt;br&gt;
        isOk: true,&lt;br&gt;
        data: data.rows?._array ?? [],&lt;br&gt;
      };&lt;br&gt;
    } catch (e) {&lt;br&gt;
      console.error(e);&lt;br&gt;
      return {&lt;br&gt;
        isOk: false,&lt;br&gt;
        data: [],&lt;br&gt;
        errorCode: e.code || 'N/A',&lt;br&gt;
        error: e.message,&lt;br&gt;
      };&lt;br&gt;
    }&lt;br&gt;
  }&lt;br&gt;
  async open(name: string): Promise {&lt;br&gt;
    try {&lt;br&gt;
      if (this._isOpen &amp;amp;&amp;amp; name === this._name) {&lt;br&gt;
        return true;&lt;br&gt;
      }&lt;br&gt;
      if (this._isOpen &amp;amp;&amp;amp; name !== this._name) {&lt;br&gt;
        await this.close();&lt;br&gt;
        this._isOpen = false;&lt;br&gt;
      }&lt;br&gt;
      this._name = name;&lt;br&gt;
      this._db = openLibsql({&lt;br&gt;
        name: this._name,&lt;br&gt;
        location: this._location,&lt;br&gt;
      });&lt;br&gt;
      console.log('Opened db');&lt;br&gt;
      this._isOpen = true;&lt;br&gt;
      return true;&lt;br&gt;
    } catch (e) {&lt;br&gt;
      // eslint-disable-next-line no-console&lt;br&gt;
      console.error("couldn't open db", e);&lt;br&gt;
      return false;&lt;br&gt;
    }&lt;br&gt;
  }&lt;/p&gt;

&lt;p&gt;async isOpen(): Promise {&lt;br&gt;
    return Promise.resolve(this._isOpen);&lt;br&gt;
  }&lt;/p&gt;

&lt;p&gt;async close(): Promise {&lt;br&gt;
    if (this.useCrSql) {&lt;br&gt;
      this._db.execute(&lt;code&gt;select crsql_finalize();&lt;/code&gt;);&lt;br&gt;
    }&lt;br&gt;
    this._db.close();&lt;br&gt;
    this._isOpen = false;&lt;br&gt;
    return Promise.resolve(true);&lt;br&gt;
  }&lt;br&gt;
}&lt;br&gt;
Now we are ready to make graph tables and indexes. I'll skip the entire class as far it is too long and give only essential parts&lt;/p&gt;

&lt;p&gt;const vectorOptions = this._store.getVectorOption()&lt;br&gt;
Give us vector configurations, such as the type of vector value and the dimension of embeddings, as the same as vector index params.&lt;/p&gt;

&lt;p&gt;const createR = await this._store.execute(&lt;code&gt;&lt;br&gt;
        create table if not exists edge (&lt;br&gt;
          id varchar(36) primary key not null,&lt;br&gt;
          fromId varchar(36) not null default '',&lt;br&gt;
          toId varchar(36) not null default '',&lt;br&gt;
          label varchar not null default '',&lt;br&gt;
          displayLabel varchar not null default '',&lt;br&gt;
          vectorTriple ${vectorOptions.type}_BLOB(${vectorOptions.dimension}),&lt;br&gt;
          createdAt real,&lt;br&gt;
          updatedAt real,&lt;br&gt;
          source varchar(36) default 'N/A',&lt;br&gt;
          type varchar default 'edge',&lt;br&gt;
          meta text default '{}'&lt;br&gt;
         );&lt;br&gt;
&lt;/code&gt;)&lt;br&gt;
Now we have a triple store that has references to nodes&lt;/p&gt;

&lt;p&gt;const createR = await this._store.execute(&lt;code&gt;&lt;br&gt;
         create table if not exists node (&lt;br&gt;
          id varchar(36) primary key not null,&lt;br&gt;
          label varchar not null default '',&lt;br&gt;
          vectorLabel ${vectorOptions.type}_BLOB(${vectorOptions.dimension}),&lt;br&gt;
          displayLabel varchar not null default '',&lt;br&gt;
          createdAt real,&lt;br&gt;
          updatedAt real,&lt;br&gt;
          source varchar(36) default 'N/A',&lt;br&gt;
          type varchar default 'node',&lt;br&gt;
          entity text default '{}',&lt;br&gt;
          meta text default '{}'&lt;br&gt;
         );&lt;br&gt;
&lt;/code&gt;)&lt;br&gt;
If you want to know how to model graphs in relational db read my article&lt;/p&gt;

&lt;p&gt;Personal Knowledge Graphs. Semantic Entity Persistence in Relational Model&lt;br&gt;
In my last two articles, we modeled different kinds of graphs in a portable relational model.&lt;br&gt;
blog.stackademic.com&lt;/p&gt;

&lt;p&gt;Time to create an index&lt;/p&gt;

&lt;p&gt;const createIndex = await this._store.execute(&lt;code&gt;CREATE INDEX IF NOT EXISTS idx_edge_vectorTriple&lt;br&gt;
 ON edge (libsql_vector_idx(vectorTriple${vectorOptions.compression !== 'none' ?&lt;/code&gt;, 'compress_neighbors=${vectorOptions.compression}'&lt;code&gt;: ''}&lt;br&gt;
 ${vectorOptions.maxNeighbors ?&lt;/code&gt;, 'max_neighbors=${vectorOptions.maxNeighbors}'&lt;code&gt;: ''}));&lt;/code&gt;)&lt;br&gt;
We configure compress_neighbors and max_neighbors to get the best storage space footprint. if you want to learn more about space complexity, read this article&lt;/p&gt;

&lt;p&gt;The space complexity of vector search indexes in LibSQL&lt;br&gt;
Hey, so I continue my adventure in vector search and Graph clustering at&lt;br&gt;
ai.plainenglish.io&lt;/p&gt;

&lt;p&gt;Now, we could create a triple&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const createOp = await this._store.execute(
  `
  insert into edge (id, fromId, toId , label, vectorTriple, displayLabel, createdAt, updatedAt)
    values (?, ? , ? , ? , vector(${this._store.toVector(
      await this.embeddingsService.embedDocument(`${fromNode.label} ${normalizedLabel} ${toNode.label}`)
    )}) , ? , ?, ?);
`,
  [
    this._getUuid(),
    fromNode.id,
    toNode.id,
    normalizedLabel,
    label,
    Date.now(),
    Date.now(),
  ]
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Unfortunately, op-sql does not support float32array as a parameter as libsql does. To make a workaround, we need to use a bit of dynamic SQL and create a serialized vector as part of queries. My toVector method does a stringify of float32array and cares about quotes. Please note that we pass a serialized array to a vector function in SQL. I hope that the next version of op-SQL will support float32arrays&lt;/p&gt;

&lt;p&gt;Time to query !!&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const _top = top ?? 10
const vector = this._store.toVector(await this.embeddingsService.embedQuery(query))

const querySql = `
select  e.id, e.label, e.displayLabel, e.createdAt, e.updatedAt, e.source, e.type , e.meta , fn.label, fn.displayLabel, tn.label, tn.displayLabel, vector_distance_cos(e.vectorTriple , ${vector}) distance
from vector_top_k('idx_edge_vectorTriple', ${vector} , ${_top}) as i
inner join edge as e on i.id = e.rowid
inner join node as fn on e.fromId = fn.id
inner join node as tn on e.toId = tn.id
where 1=1 ${maxDistance ? `and  distance &amp;lt;= ${maxDistance}` : ''}
order by distance
limit ${_top};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;`&lt;br&gt;
    const edgeData = await this._store.query(querySql)&lt;br&gt;
Few notes&lt;/p&gt;

&lt;p&gt;by default, the vector index works and returns rowid so be careful that the joins&lt;br&gt;
index does not return distance. Still, you could calculate it if you needed&lt;br&gt;
vector_top_k expect top parameter and will return top N items. If you have complex filtering or external top limitations, remember to set a much bigger top N to make the search possible. In our case it is not an issue.&lt;br&gt;
Issues and challenges&lt;br&gt;
I faced a few challenges in React Native, mainly for iOS. They are related to how native modules are compiled and linked in iOS.&lt;/p&gt;

&lt;p&gt;One quite unpleasant issue — if you have another library that use another version of Sqlite — it could unpredictably override linking and broke libsql completely.&lt;/p&gt;

&lt;p&gt;Compilation Clashes&lt;br&gt;
If you have other packages that are dependent on sqlite (specially if they compile it from source) you will have issues.&lt;/p&gt;

&lt;p&gt;Some of the known offenders are:&lt;/p&gt;

&lt;p&gt;expo-updates&lt;br&gt;
expo-sqlite&lt;br&gt;
cozodb&lt;br&gt;
You will face duplicated symbols and/or header definitions since each of the packages will try to compile SQLite from sources. Even if they manage to compile, they might compile sqlite with different compilation flags and you might face threading errors.&lt;/p&gt;

&lt;p&gt;Unfortunately, there is no easy solution. It would be best if you got rid of the double compilation by hand, either by patching the compilation of each package so that it still builds or removing the dependency on the package.&lt;/p&gt;

&lt;p&gt;On Android you might be able to get away by just using a pickFirst strategy (here is an article on how to do that). On iOS depending on the build system you might be able to patch it via a post-build hook, something like:&lt;/p&gt;

&lt;p&gt;pre_install do |installer|&lt;br&gt;
 installer.pod_targets.each do |pod|&lt;br&gt;
  if pod.name.eql?('expo-updates')&lt;br&gt;
   # Modify the configuration of the pod so it doesn't depend on the sqlite pod&lt;br&gt;
  end&lt;br&gt;
 end&lt;br&gt;
end&lt;br&gt;
Follow op-sql docs to get an updated list of libs&lt;/p&gt;

&lt;p&gt;Gotchas | Notion&lt;br&gt;
Built with Notion, the all-in-one connected workspace with publishing capabilities.&lt;br&gt;
ospfranco.notion.site&lt;/p&gt;

&lt;p&gt;RNRestart crash&lt;br&gt;
One more ios issue&lt;/p&gt;

&lt;p&gt;import RNRestart from 'react-native-restart';&lt;br&gt;
if you for some reasons need to restart app and use react-native-restart you need to make that you close all connections&lt;/p&gt;

&lt;p&gt;import { closeAllConnections } from '@storage/data-store-factory';&lt;br&gt;
import RNRestart from 'react-native-restart';&lt;br&gt;
export const restartApplication = async (): Promise =&amp;gt; {&lt;br&gt;
  await closeAllConnections();&lt;br&gt;
  RNRestart.restart();&lt;br&gt;
};&lt;br&gt;
Now you could also do a personal knowledge graph with vector search on a user device!!!&lt;/p&gt;

&lt;p&gt;I want to say thanks to Oskar and Turso team for their amazing work &lt;/p&gt;

</description>
      <category>libsql</category>
      <category>reactnative</category>
      <category>sql</category>
      <category>vectorsearch</category>
    </item>
    <item>
      <title>Fastest way to count in sql</title>
      <dc:creator>Volodymyr Pavlyshyn</dc:creator>
      <pubDate>Wed, 11 Sep 2024 15:47:46 +0000</pubDate>
      <link>https://dev.to/volland/fastest-way-to-count-in-sql-23m</link>
      <guid>https://dev.to/volland/fastest-way-to-count-in-sql-23m</guid>
      <description>&lt;p&gt;We all know that stars in a select statement are a terrible idea&lt;/p&gt;

&lt;p&gt;select * from message ;&lt;br&gt;
It could give unpredictable results over time with schema evolution and give unoptimized queries, so good practice is to select what you need !!&lt;/p&gt;

&lt;p&gt;Good star in SQL&lt;br&gt;
Well, only some starts are good. One particular star is a good one!&lt;/p&gt;

&lt;p&gt;Count (*): Tell your database to count rows of tables as fast as possible! It is a bit counterintuitive, but let's examine it further.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
sql
select count(id) from message ;
┌───────────┐
│ count(id) │
├───────────┤
│ 1091      │
└───────────┘
Run Time: real 0.001 user 0.000170 
As you see on timing, it is fast, but we have a quicker result possible with

libsql&amp;gt; select count(*) from message ;
┌──────────┐
│ count(*) │
├──────────┤
│ 1091     │
└──────────┘
Run Time: real 0.000 user 0.000093 
How is it possible?

Let's ask explain

libsql&amp;gt; explain query plan select count(*) from message ;
QUERY PLAN
`--SCAN message USING COVERING INDEX idx_message_conversation
As we can see, it uses a secondary index much smaller than a clustering index that keeps a row of data. So, if you have any secondary indexes, the majority of query planers will use it for a fast count.

So even if it is counter-intuitive not all stars are bed in SQL


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>sql</category>
    </item>
    <item>
      <title>Personal Knowledge Graphs in AI RAG-powered Applications with libSQL</title>
      <dc:creator>Volodymyr Pavlyshyn</dc:creator>
      <pubDate>Sun, 18 Aug 2024 09:02:32 +0000</pubDate>
      <link>https://dev.to/volland/personal-knowledge-graphs-in-ai-rag-powered-applications-with-libsql-m3d</link>
      <guid>https://dev.to/volland/personal-knowledge-graphs-in-ai-rag-powered-applications-with-libsql-m3d</guid>
      <description>&lt;p&gt;I spend a long time working on privacy first personal ai assistant&lt;/p&gt;

&lt;p&gt;Our application is localfirst and focused on sovereign data ownership. So, one of the challenges was finding the proper storage of data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Device friendly
&lt;/h2&gt;

&lt;p&gt;I partially describe several options for embeddable and device-friendly databases in my previous article&lt;/p&gt;

&lt;p&gt;AI-powered apps, especially the semantic memory part, set few expectations for database capabilities&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  general queries on structured data (regular application data) like messages, conversations, settings, etc&lt;/li&gt;
&lt;li&gt;  vector search and similarity search capabilities to RAG pipelines and different LLM and ML-powered flows&lt;/li&gt;
&lt;li&gt;  Graph and graph search capabilities (ML and semantic memory )&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As far as we work on mobile, we have a few tech capabilities, too&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  embeddable with good support for mobile bindings&lt;/li&gt;
&lt;li&gt;  single file database that simplifies a backup&lt;/li&gt;
&lt;li&gt;  portable&lt;/li&gt;
&lt;li&gt;  battery friendly&lt;/li&gt;
&lt;li&gt;  fast and nonblocking io as much as possible&lt;/li&gt;
&lt;li&gt;  wide community support&lt;/li&gt;
&lt;li&gt;  reliability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vector and Graph capabilities for embeddable databases were relatively new challenges for modern databases. The close competitor was Postgress, with extensions that add&lt;/p&gt;

&lt;p&gt;and&lt;/p&gt;

&lt;p&gt;So, we need a similar embeddable setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Graphs
&lt;/h2&gt;

&lt;p&gt;Currently, there are practically no graph-oriented databases that have portable and embeddable capabilities with a mobile or small device friend setup.&lt;/p&gt;

&lt;p&gt;I made a few articles to model and show how to use relational databases for graph and hypergraph capabilities. It is a wide topic that has a lot of exciting research topics. You can find more about it in my articles.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vectors
&lt;/h2&gt;

&lt;p&gt;It is a wide variety of vector databases and libraries on the market. Some of the libraries like faiss .&lt;/p&gt;

&lt;p&gt;It is top-performing and even has some capabilities to persist sectors to a file. So, it was a good start, but...&lt;/p&gt;

&lt;p&gt;It is a big challenge to keep heterogeneous data storages in sync, and even the process of sync will consume time, battery, and CPU resources of an application and eat the main thread of the app that will, making it less and less user-friendly.&lt;/p&gt;

&lt;p&gt;For me, it was clear — we need something integrated into a database.&lt;/p&gt;

&lt;p&gt;After weeks of research and a prototype, we stopped at the SQLite ecosystem. SQLite has been the most popular and reliable database for mobile devices for decades.&lt;/p&gt;

&lt;p&gt;But what about vectors?&lt;/p&gt;

&lt;p&gt;SQLite has an extendable architecture that allows native modules to extend a database capability. I found this project that brings faiss to a SQLite.&lt;/p&gt;

&lt;p&gt;Unfortunately, it was not reliable and had a few major bugs and issues, so I almost gave up.&lt;/p&gt;

&lt;p&gt;We were lucky to find a better answer to our question&lt;/p&gt;

&lt;p&gt;Libsql is open to contribution. It is an open-source replacement for SQLite that brings many features and performance optimization to the table. Some of these features deserve a separate article,&lt;/p&gt;

&lt;p&gt;like :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  alter table extension that makes a migration easy&lt;/li&gt;
&lt;li&gt;  webassembly defined functions !&lt;/li&gt;
&lt;li&gt;  Virtual WAL interface&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and much more&lt;/p&gt;

&lt;p&gt;but the most critical one is that it extends SQLite with vector search capabilities.&lt;/p&gt;

&lt;p&gt;It is built smartly with minimal database changes, so it is easy to migrate and still compatible with SQLite.&lt;/p&gt;

&lt;p&gt;It is no vector type, or let's say it is aliased on top of BLOB&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE TABLE node (
          id varchar(36) primary key not null,
          label varchar not null default '',
          vectorLabel F32_BLOB(512) ,
          displayLabel varchar not null default '',
          createdAt real,
          updatedAt real
         );
CREATE TABLE edge (
          id varchar(36) primary key not null,
          fromId varchar(36) not null default '',
          toId varchar(36) not null default '',
          label varchar not null default '',
          displayLabel varchar not null default '',
          vectorTriple F32_BLOB(512) ,
          createdAt real,
          updatedAt real,
         );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So &lt;strong&gt;F32_BLOB(512)&lt;/strong&gt; specifies a meta information about a vector. It is a value type float 32-bit and a dimension of the array.&lt;/p&gt;

&lt;p&gt;This type is more an alliance on BLOB but it gives a posibility to a database to validate a vector shape and it is data types&lt;/p&gt;

&lt;p&gt;Now we have the ability to use a vector search for clustering a Graph and use it in a LLM powered pipelines&lt;/p&gt;

&lt;p&gt;On edge, we store few meta information about triple&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  display label — describe edge label un normalized one&lt;/li&gt;
&lt;li&gt;  label — normalized label&lt;/li&gt;
&lt;li&gt;  vectorTripple — is the most interesting part. we normalize a node labels and edge label and concat them together. it allows us to make embedding out of it and make edges searchable by vector search&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our vectorTripple column adds a vector search capability to our personal knowledge graph .&lt;/p&gt;

&lt;p&gt;To insert data we could use a vector function that gets embedding as :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  float32 array&lt;/li&gt;
&lt;li&gt;  a blob of serialized float32 array&lt;/li&gt;
&lt;li&gt;  string representation like ‘[0.5432635, 0.3333 ….]’
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;insert into edge (rowid, id, fromId, toId , label, vectorTriple, displayLabel, createdAt, updatedAt)
  values (? , ?, ? , ? , ? , vector(${this._store.toVector(
          await this.embeddingsService.embedDocument(`${fromNode.label} ${normalizedLabel} ${toNode.label}`)
        )}) , ? , ?, ?);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With &lt;strong&gt;vector_distance_cos&lt;/strong&gt; function we could already do a distance calculation and queries&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;select  e.id, e.label, vector_distance_cos(e.vectorTriple , ${vector}) distance 
from egde e 
where distance &amp;lt; 0.15
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is fantastic but very slow and ineffective and CPU intensive as far as you need to scan the full table and calculate the distances. So, we need a vector index.&lt;/p&gt;

&lt;p&gt;We are lucky we can create an index for embedding columns !!!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE INDEX idx_edge_vectorTriple ON edge (libsql_vector_idx(vectorTriple));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, instead of a full scan, we could search in the index&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;select  e.id, e.label, vector_distance_cos(e.vectorTriple , vector('[0.32323, 0.525, ....]')) distance
    from vector_top_k('idx_edge_vectorTriple', vector('[0.32323, 0.525, ....]'), ${_top}) as i
    inner join edge as e on i.id = e.rowid
    inner join node as fn on e.fromId = fn.id
    inner join node as tn on e.toId = tn.id
    where distance &amp;lt;= 0.15`
    order by distance
    limit 20;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So let's step by&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vector_top_k('idx_edge_vectorTriple', '[0.32323, 0.525, ....]', 20) as i
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will give us back &lt;strong&gt;rowIDs&lt;/strong&gt; of similarity and vector search from index &lt;strong&gt;idx_edge_vectorTriple&lt;/strong&gt;, based on the &lt;strong&gt;vectorTriple&lt;/strong&gt; column.&lt;/p&gt;

&lt;p&gt;You should be careful. By default, it uses rowid. So, to combine the result of the vector search with any data and tables in your DB, you need to use a simple join statement. All is an integral part of the base and queriable&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;inner join edge as e on i.id = e.rowid
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The index does not return distances, so you still need to calculate them yourself self, but now it happens on the way smaller dataset&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;select  e.id, e.label, vector_distance_cos(e.vectorTriple , vector('[0.32323, 0.525, ....]')) distance
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;vector function is a smart move that converts string like ‘[1,32,2, …. ]’ to a blob type that stored in a database&lt;/p&gt;

&lt;p&gt;Now you could do an extra filter on distances if you need to find close related triples&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;where distance &amp;lt;= 0.15
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have a vector search on top of personal Knowledge&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Personal Knowledge Graphs can be modeled in a relation model and are usually relatively middle-sized, so they never lead to performance issues with SQL queries. With Libsql, we have native and low-level support of vectors. It allows us to build a clustering of the graph and RAG pipelines on the user devices if needed. This feature is still under active development and may require some time, but from my experience, it is stable now.&lt;/p&gt;

</description>
      <category>libsql</category>
      <category>rag</category>
      <category>vectorsearch</category>
    </item>
    <item>
      <title>Multimillion Common Programming Language Mistakes and Better Approaches</title>
      <dc:creator>Volodymyr Pavlyshyn</dc:creator>
      <pubDate>Sun, 18 Aug 2024 09:00:45 +0000</pubDate>
      <link>https://dev.to/volland/multimillion-common-programming-language-mistakes-and-better-approaches-37fa</link>
      <guid>https://dev.to/volland/multimillion-common-programming-language-mistakes-and-better-approaches-37fa</guid>
      <description>&lt;p&gt;Modern programming languages have evolved considerably, yet certain design flaws and pitfalls remain pervasive, causing significant challenges and costs in software development. This article explores some of these common mistakes and presents alternative approaches to mitigate their impact, as discussed in a recent insightful video.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Null Problem
&lt;/h2&gt;

&lt;p&gt;One of the most notorious issues in programming is the concept of null references. Tony Hoare, the inventor of the null reference, even referred to it as his “billion-dollar mistake” due to the numerous errors and system crashes it has caused. To avoid null-related issues, several strategies can be employed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Option and Maybe Types:&lt;/strong&gt; Languages like Java and C# offer options or monads that encapsulate values that may be null, providing a safer way to handle optional values.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dependent Types&lt;/strong&gt;: These types allow more logic to be moved to the type system, ensuring null-free code.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Libraries and Optional Chains&lt;/strong&gt;: JavaScript has adopted optional chaining, which, while not perfect, significantly reduces null-related errors.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Handling Errors
&lt;/h2&gt;

&lt;p&gt;Exception handling in programming languages has often been criticized for its complexity and propensity to introduce bugs. Traditional try-catch blocks can lead to cumbersome and error-prone code. Alternative approaches include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Monadic Interfaces:&lt;/strong&gt; Using monads to handle errors as values can improve code readability and safety. Languages like Haskell and Scala employ this method effectively.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Algebraic Effects:&lt;/strong&gt; This advanced technique separates error handling from the main code logic, allowing for more flexible and maintainable error management.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Coloring Functions
&lt;/h2&gt;

&lt;p&gt;The concept of “coloring” functions refers to the practice of marking functions as asynchronous (async). This can lead to a cascade effect where many functions must be marked async, complicating codebases. Algebraic effects offer a solution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Algebraic Effects and Handlers&lt;/strong&gt;:By using algebraic effects, asynchronous operations and error handling can be integrated more seamlessly, reducing the need for widespread async function declarations.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Concurrent Programming and Locks
&lt;/h2&gt;

&lt;p&gt;Concurrency introduces significant complexity, often leading to difficult-to-diagnose bugs. Traditional methods like locks and threads can be error-prone. Better alternatives include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Actor Model&lt;/strong&gt;: This model, used in languages like Erlang and frameworks like Akka, encapsulates state and behavior within actors, making concurrency more manageable.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Go-like Channels&lt;/strong&gt;: Go uses channels to facilitate communication between goroutines, simplifying concurrent programming by abstracting the complexities of thread management.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Fragile Classes and Overuse of Inheritance
&lt;/h2&gt;

&lt;p&gt;Object-oriented programming (OOP) and inheritance can lead to fragile base class problems and excessive complexity. Alternatives to traditional class-based inheritance include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Prototypal Inheritance:&lt;/strong&gt; JavaScript utilizes prototypes, where objects inherit directly from other objects. This approach can be more flexible and less error-prone than classical inheritance.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data-Oriented Programming:&lt;/strong&gt; Focusing on data and its transformations rather than the objects can lead to more maintainable and understandable code.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By acknowledging and addressing these common pitfalls in programming languages, developers can write more robust, maintainable, and error-free code. Embracing advanced techniques such as monads, algebraic effects, actor models, and prototypal inheritance can significantly enhance the quality and reliability of software systems. As the field of software development continues to evolve, it’s crucial to stay informed about these approaches and incorporate them into your programming practices.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>HyperGraphs In Relation Model</title>
      <dc:creator>Volodymyr Pavlyshyn</dc:creator>
      <pubDate>Mon, 08 Apr 2024 12:37:07 +0000</pubDate>
      <link>https://dev.to/volland/hypergraphs-in-relation-model-1djn</link>
      <guid>https://dev.to/volland/hypergraphs-in-relation-model-1djn</guid>
      <description>&lt;p&gt;In my last article, we model different kinds of graphs in abstract relational databases.&lt;/p&gt;

&lt;p&gt;We talk about hypergraphs and even model Undirected hypergraphs. Let's recap our undirected models.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KS9KkdZq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:518/1%2ApU41iOpJLu7FaY0ohPm9mQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KS9KkdZq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:518/1%2ApU41iOpJLu7FaY0ohPm9mQ.png" alt="" width="259" height="323"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hypergraph&lt;/p&gt;

&lt;h2&gt;
  
  
  Undirected Hypergraph
&lt;/h2&gt;

&lt;p&gt;A hypergraph is a mathematical generalization of graphs where a hyperedge could connect multiple or no nodes. So, you have a set of nodes instead of a pair of nodes. Hypergraphs are an emerging domain for modeling complex and dynamic systems and are widely used for temporal and event-dependent graphs. We will model undirected hypergraphs.&lt;br&gt;&lt;br&gt;
Usually, a hypergraph is drawn assets that overlap or as Vin diagrams.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LyZj4yHc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/0%2A31ovMcVCT9Md696T.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LyZj4yHc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/0%2A31ovMcVCT9Md696T.png" alt="" width="786" height="806"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As far as edges now have many-to-many relations with nodes, we just need a joint table.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_522smY---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/0%2A2RamC6jTMrfb-hIj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_522smY---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/0%2A2RamC6jTMrfb-hIj.png" alt="" width="772" height="624"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nodes&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WGbeJIGM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:780/0%2AAj6NeN-EtFWyO6bd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WGbeJIGM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:780/0%2AAj6NeN-EtFWyO6bd.png" alt="" width="390" height="592"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Edges&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DvM2jT1M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:844/0%2APU17vqkrwNHcgUWT.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DvM2jT1M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:844/0%2APU17vqkrwNHcgUWT.png" alt="" width="422" height="644"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Edge to nodes&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MkqTQE3n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:992/0%2AxJOyXHtpFjcQ4Ggd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MkqTQE3n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:992/0%2AxJOyXHtpFjcQ4Ggd.png" alt="" width="496" height="1114"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The table could increase if you have a significant edge with a comprehensive set of nodes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Directed HyperGraph
&lt;/h2&gt;

&lt;p&gt;In directed HyperGraph, we divide nodes into a subset of in-nodes and out-nodes. So, we have a directed edge from one subset to another subset.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--r-aEubYB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/1%2A9MbGKWa7rpxobEVsaRZ2Eg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r-aEubYB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/1%2A9MbGKWa7rpxobEVsaRZ2Eg.png" alt="" width="800" height="796"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have multiple options for modeling this structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  As directed, edge-node relations
&lt;/h2&gt;

&lt;p&gt;The most straightforward way is to add a direction attribute to edge-node pairs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GHEV0QZg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/1%2AL7lLXRiTBjKhIN4jzgpGlA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GHEV0QZg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/1%2AL7lLXRiTBjKhIN4jzgpGlA.png" alt="" width="800" height="647"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now Nodes and edges stay the same as in preve example&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JHVBG0aD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1196/1%2A_Syo-G7Tqoy88sTI504sHw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JHVBG0aD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1196/1%2A_Syo-G7Tqoy88sTI504sHw.png" alt="" width="598" height="1238"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But relations now has a directions&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NdJdHzPA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/1%2A-kmlkaKP2e1HReK9s4fTew.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NdJdHzPA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/1%2A-kmlkaKP2e1HReK9s4fTew.png" alt="" width="734" height="1126"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros of this model&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  simplicity&lt;/li&gt;
&lt;li&gt;  ability to create mixed graphs — directed and undirected&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons of this model&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  it could be hard to build queries&lt;/li&gt;
&lt;li&gt;  The model could encode invalid states. Nobody prevents us from having the same node on the same edge in two directions.&lt;/li&gt;
&lt;li&gt;  for a strictly directed graph we need extra application-level constraints&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  As directed Graph of nodesets
&lt;/h2&gt;

&lt;p&gt;We could be more explicit and extend a model from a directed graph to operate with node sets&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dqqj8dFw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/1%2A8kKo9STHX0OyQS9KiuB0Hw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dqqj8dFw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/1%2A8kKo9STHX0OyQS9KiuB0Hw.png" alt="" width="800" height="926"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, the source and object of the edge point to a node-set relation. For simplicity, we expect that in the case of individual nodes, we create separate node-set for these nodes&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros of this model&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  more explicit&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons of this model&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Require to create a node set for single nodes&lt;/li&gt;
&lt;li&gt;  more complex&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>hypergraphs</category>
      <category>db</category>
      <category>ai</category>
      <category>knowledgegraphs</category>
    </item>
    <item>
      <title>Personal Knowledge Graphs in Relational Model</title>
      <dc:creator>Volodymyr Pavlyshyn</dc:creator>
      <pubDate>Mon, 08 Apr 2024 12:35:21 +0000</pubDate>
      <link>https://dev.to/volland/personal-knowledge-graphs-in-relational-model-59e9</link>
      <guid>https://dev.to/volland/personal-knowledge-graphs-in-relational-model-59e9</guid>
      <description>&lt;p&gt;Various graph databases offer functionalities with a wide range of graph-oriented query languages, from Cypher to graphQL and custom ones. Graph databases could be optimized for storing and processing big graphs but require time to master and learn, and sometimes, it has quite a step in the learning curve. Personal Knowledge Graphs usually have a much smaller scale and are part of user applications or personal knowledge systems.&lt;/p&gt;

&lt;p&gt;In a classical application, only a part of the data has a graph nature, and we could have a mixed setup of regular relational data and graphs.&lt;br&gt;&lt;br&gt;
In AI-powered applications, we have a mixed case of&lt;br&gt;&lt;br&gt;
- graph data&lt;br&gt;&lt;br&gt;
- vectors and vector indexes&lt;br&gt;&lt;br&gt;
- regular documents&lt;/p&gt;

&lt;p&gt;It is hard to find a database that satisfies all these conditions.&lt;/p&gt;

&lt;p&gt;I have been happy with CozoDB for a long time. You could combine PGvector and Apache AGE for Postgres and, together with Postgress's document-like features, build a lot. Sometimes, we need embeddable databases, and we hear the leader is SQLite. We are still waiting for a PGlite implementation that brings Postgres on edge.&lt;br&gt;&lt;br&gt;
We will avoid discussing the scalability of relational databases and load it as a topic for a separate article. Still, relational structures are widespread and well-known and offer many tools. They have good Developer Experience.&lt;/p&gt;

&lt;p&gt;Graphs are not relational structures, but we could try to adopt relations to achieve a good representation and performance.&lt;/p&gt;

&lt;p&gt;If you have small and fixed graphs, you could represent them as an Adjacent matrix, but this model needs to be more scalable. Any model should be optimized for your queries and needs; current models are subjective.&lt;/p&gt;
&lt;h2&gt;
  
  
  Directed Graph
&lt;/h2&gt;

&lt;p&gt;A simple and common type of graph is a simple-directed graph where edges connect to nodes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DFJ7Balb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/1%2A0JPGzFQQ0-GKxtEE1mFj-A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DFJ7Balb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/1%2A0JPGzFQQ0-GKxtEE1mFj-A.png" alt="" width="800" height="251"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is easy to model as a relational structure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UUfW1RNl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:684/1%2AMcvh9xCIlsWmulw4RRxarw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UUfW1RNl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:684/1%2AMcvh9xCIlsWmulw4RRxarw.png" alt="" width="342" height="636"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So sample data&lt;/p&gt;

&lt;p&gt;Nodes&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--em-hgyat--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:664/1%2AR8coJTKVZEJlJpbuAgPHIQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--em-hgyat--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:664/1%2AR8coJTKVZEJlJpbuAgPHIQ.png" alt="" width="332" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Edges&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Z7PwnTcJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1148/1%2ABjOHpVd1YTEUGSCdYbsBRQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Z7PwnTcJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1148/1%2ABjOHpVd1YTEUGSCdYbsBRQ.png" alt="" width="574" height="468"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  RDF Like Graphs
&lt;/h2&gt;

&lt;p&gt;In the Resource definition framework, nodes and edges are not directly differentiated, and you could use edge and node in a different context if needed. All data is stored as triples of resources. Sometimes, modeling graphs closer to RDF is helpful, but reasoning and building queries in this model are hard. I prefer separate relations for nodes and edges.&lt;br&gt;&lt;br&gt;
ClassicaL RDF does not have a label and models it as a tripel relation, but as far as labels are concerned, I add it as a column.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7DBFI3t_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:788/1%2A0jb6zigXL5rKCh06cj_Qog.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7DBFI3t_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:788/1%2A0jb6zigXL5rKCh06cj_Qog.png" alt="" width="394" height="638"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Resource&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--P9KAqTZC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:708/1%2AtAkNdwhg9aWJG4TnZ_sAWg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P9KAqTZC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:708/1%2AtAkNdwhg9aWJG4TnZ_sAWg.png" alt="" width="354" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Triple&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TqeAJQgO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1368/1%2Az7YiBwgrHmL7gHQGzTCEVw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TqeAJQgO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1368/1%2Az7YiBwgrHmL7gHQGzTCEVw.png" alt="" width="684" height="446"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Named Graphs and Graph of Graphs
&lt;/h2&gt;

&lt;p&gt;The concept of the named graph came from the RDF community, which needed to group some sets of triples. In this way, you form subgraphs inside an existing graph. You could refer to the subgraph as a regular node. This setup simplifies complex graphs, introduces hierarchies, and even adds features and properties of hypergraphs while keeping a directed nature.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MYKklFdX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/1%2AxYPdyW2iEveDffqbFRGR8A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MYKklFdX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/1%2AxYPdyW2iEveDffqbFRGR8A.png" alt="" width="800" height="633"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It looks complex, but it is easy to model it with slightly modifying a directed graph.&lt;br&gt;&lt;br&gt;
So, the node could host graphs inside. Let's reflect this fact with a location for a node. If a node belongs to a main graph, we could set the location to null or introduce a main node . it is up to you&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--J9Solevk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1104/1%2A5nEswOiVoj6yj4IuIRPQhA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--J9Solevk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1104/1%2A5nEswOiVoj6yj4IuIRPQhA.png" alt="" width="552" height="734"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nodes could have edges to nodes in different subgraphs. This structure allows any nesting graphs. Edges stay location-free&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6QMUWTtq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1268/1%2AY-PT_yCCBuLBtaQJHSbY2w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6QMUWTtq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1268/1%2AY-PT_yCCBuLBtaQJHSbY2w.png" alt="" width="634" height="1140"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Hypergraph
&lt;/h2&gt;

&lt;p&gt;A hypergraph is a mathematical generalization of graphs where a hyperedge could connect multiple or no nodes. So, you have a set of nodes instead of a pair of nodes. Hypergraphs are an emerging domain for modeling complex and dynamic systems and are widely used for temporal and event-dependent graphs. We will model undirected hypergraphs.&lt;br&gt;&lt;br&gt;
Usually, a hypergraph is drawn as sets that overlap or as Vin diagrams.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AmovcSrJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/1%2AyQvk0BKCLPeaux4-nTMt4w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AmovcSrJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/1%2AyQvk0BKCLPeaux4-nTMt4w.png" alt="" width="786" height="806"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As far as edges now has many-to-many relations with nodes we just need a joint table&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ceH9mwwG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/1%2Ao7n2JYVeANQ2mNclwJXr9Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ceH9mwwG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/1%2Ao7n2JYVeANQ2mNclwJXr9Q.png" alt="" width="772" height="624"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nodes&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RuEzvCPj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:780/1%2AUha9P07UxzvVyg1lNtFK2A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RuEzvCPj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:780/1%2AUha9P07UxzvVyg1lNtFK2A.png" alt="" width="390" height="592"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Edges&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9nqZYpQG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:844/1%2A3SnU3SB56jiKlN2T9NcAbQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9nqZYpQG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:844/1%2A3SnU3SB56jiKlN2T9NcAbQ.png" alt="" width="422" height="644"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Edge to nodes&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hUCWbn9v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:992/1%2A7NZbUtqISj-TrVEBPiJ0RA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hUCWbn9v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:992/1%2A7NZbUtqISj-TrVEBPiJ0RA.png" alt="" width="496" height="1114"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The table could grow quickly if you have a big edge with a wide set of nodes.&lt;/p&gt;
&lt;h2&gt;
  
  
  HyperGraph with Edges as Nodes
&lt;/h2&gt;

&lt;p&gt;As you noticed, we could point the Me node to KGraph because Kgraph is now an edge. So, in a Hypergraph, edges are a set of nodes. If we want to have a graph of graph-like setup, we need the ability to use edges as nodes, the same as the RDF framework does with a resource.&lt;br&gt;&lt;br&gt;
We could simplify a lot of relations and create more complex structures.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eANJh4C2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/1%2ArT7-VNHZ0-T99NtUKBpE8A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eANJh4C2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/1%2ArT7-VNHZ0-T99NtUKBpE8A.png" alt="" width="760" height="824"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To achieve this, we could combine an RDF-like schema with a hypergraph schema. The model would still remain relatively simple.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--k5H0MUl5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:728/1%2AKGCP_kBiJVFCA_5ntcXHmQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k5H0MUl5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:728/1%2AKGCP_kBiJVFCA_5ntcXHmQ.png" alt="" width="364" height="582"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;we couldn’t reuse edges like we did in RDF because they contain different resources.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VJO-ZDC---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:840/1%2AMfXqGOzMFjU_8h5FVoYmPQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VJO-ZDC---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:840/1%2AMfXqGOzMFjU_8h5FVoYmPQ.png" alt="" width="420" height="1022"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cL5lv1Ey--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1092/1%2A364KXnC8LJ6RX7w3w0t5dA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cL5lv1Ey--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1092/1%2A364KXnC8LJ6RX7w3w0t5dA.png" alt="" width="546" height="1172"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We could deduce pure nodes and edges from relations. Unfortunately, as long as you allow empty edges, there is no way to differentiate empty edges from single nodes. Hypergraphs could model named graphs and graphs of graphs, but from my experience, named graphs are more convenient for using nodes with a location.&lt;/p&gt;
&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Relational and embeddable databases could be a good choice for small-scale and personal Knowledge graphs. I have had a lot of positive experience with graph structure on a relations model with a datalog. Also, any datalog database with persistence could give you good results. Most static fact-based semantics graphs work well with a simple directed graph. I am increasingly working with AI applications in which complex ideas, conversations, or events could contain subgraphs and multiple entities. In this case, a directed graph or simple triple is not enough. As for me, graphs of graphs and named graphs give good results for this task and still stay close to what SPARQL 1.1 and Turtle could model.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;span id="3b27" data-selectable-paragraph=""&amp;gt;# N-Graphs&amp;lt;br&amp;gt;&amp;amp;lt;http://example.org/alice/foaf.rdf&amp;amp;gt; {&amp;lt;br&amp;gt;  &amp;amp;lt;http://example.org/alice/foaf.rdf#me&amp;amp;gt; &amp;amp;lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#type&amp;amp;gt; &amp;amp;lt;http://xmlns.com/foaf/0.1/Person&amp;amp;gt; .&amp;lt;br&amp;gt;  &amp;amp;lt;http://example.org/alice/foaf.rdf#me&amp;amp;gt; &amp;amp;lt;http://xmlns.com/foaf/0.1/name&amp;amp;gt;                  "Alice"  .&amp;lt;br&amp;gt;}&amp;lt;br&amp;gt;&amp;amp;lt;http://example.org/bob/foaf.rdf&amp;amp;gt; {&amp;lt;br&amp;gt;  &amp;amp;lt;http://example.org/bob/foaf.rdf#me&amp;amp;gt;   &amp;amp;lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#type&amp;amp;gt; &amp;amp;lt;http://xmlns.com/foaf/0.1/Person&amp;amp;gt; .&amp;lt;br&amp;gt;  &amp;amp;lt;http://example.org/bob/foaf.rdf#me&amp;amp;gt;   &amp;amp;lt;http://xmlns.com/foaf/0.1/name&amp;amp;gt;                  "Bob" .&amp;lt;br&amp;gt;}&amp;lt;/span&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hypergraphs are a more robust and new tool well suited for complex dynamic and temporal aware systems. It is not so much standard tools that work with hypergraphs as industry standards. Hypergraphs where edges could be used as nodes deviate from a classical mathematical model but give the most flexible platform for modeling. Sometimes, this model could simplify the amount of edges. More general models is simple to store but more complex to reason and query so you need to find a balance yourself.&lt;/p&gt;

</description>
      <category>sql</category>
      <category>graphs</category>
      <category>hypergraph</category>
      <category>ai</category>
    </item>
    <item>
      <title>Don't Sell SSI … build on top of it. Outlook of 2023 in SSI journey</title>
      <dc:creator>Volodymyr Pavlyshyn</dc:creator>
      <pubDate>Sun, 31 Dec 2023 10:40:53 +0000</pubDate>
      <link>https://dev.to/volland/dont-sell-ssi-build-on-top-of-it-outlook-of-2023-in-ssi-journey-1jii</link>
      <guid>https://dev.to/volland/dont-sell-ssi-build-on-top-of-it-outlook-of-2023-in-ssi-journey-1jii</guid>
      <description>&lt;ul&gt;
&lt;li&gt;  don't sell SSI build on top&lt;/li&gt;
&lt;li&gt;  we need agents, not wallets&lt;/li&gt;
&lt;li&gt;  we don't need VC for everything&lt;/li&gt;
&lt;li&gt;  DWNs as ssi on steroids&lt;/li&gt;
&lt;li&gt;  AI needs SSI for the future&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As we enter a new year, it’s a time for reflection and forward-thinking, especially in technology and data privacy. My journey with Self-Sovereign Identity (SSI) and Sovereign data has been a significant part of my professional life, and I’d like to share some insights and realizations from this journey.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Shift in Focus: From Selling SSI to Building Value-Driven Products
&lt;/h2&gt;

&lt;p&gt;Over the past year, there has been a significant shift in my approach to SSI. Like many in the field, I was initially captivated by the potential of SSI technology. We believed it could transform society and various projects. However, the reality proved to be different. Simply selling or packaging the technology as a shiny new solution isn’t enough. This approach led to a lack of adoption and understanding, as people found it complex and challenging.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Realization: Technology Must Solve Real-Life Problems
&lt;/h2&gt;

&lt;p&gt;The key realization was that technology, including SSI, must be more than an innovative concept. It must address real-life problems and offer tangible value to users. This year, I’ve aligned with a team that shares my values and focuses on creating products that enhance privacy and security. Our goal is to build tools that respect user data privacy and offer practical solutions to everyday challenges.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Product: A Privacy-First Personal Assistant
&lt;/h2&gt;

&lt;p&gt;One of our exciting projects is a privacy-first personal assistant. This tool is designed to keep user data secure and private, operating with a local-first and, eventually, offline-first approach. This presents unique challenges, as it involves running applications directly on devices, a path less traveled in the tech world.&lt;/p&gt;

&lt;h2&gt;
  
  
  Beyond Technology: Creating a Network of Networks
&lt;/h2&gt;

&lt;p&gt;Looking ahead, the potential of SSI extends beyond individual applications. We envision a future where personal knowledge graphs and semantic memories, already available in some of our tools, can connect to broader social structures. This could lead to the development of artificial identity agents that understand and interact with our complex social networks, reflecting our multiple identities and the groups we associate with.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Challenge with Wallets and the Need for Agents
&lt;/h2&gt;

&lt;p&gt;Another area of exploration is the concept of digital wallets. While they are often touted as revolutionary, I see them as a barrier to adoption due to their complexity and maintenance requirements. The future might lie in developing agents that can act on behalf of users, balancing security, sovereignty, and usability.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Trust is not verifiable, and data is not only VCs&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We are moving away from the concept of Verifiable data for everything. Current versions of verifiable data simply have too many security and trust challenges.&lt;/p&gt;

&lt;h2&gt;
  
  
  DWN, Web5, and SSI on steroids
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bQGj_oVl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/1%2ArgrvlHO665x_tH44_3Kehw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bQGj_oVl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/1%2ArgrvlHO665x_tH44_3Kehw.png" alt="" width="800" height="590"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;DWN took a unique path in decentralized storage, offering a relay-based topology with permissions, encryption, and synchronization capabilities. This approach particularly benefits DApps and AI agents requiring extensive data storage. DWNs balance local and networked data storage, providing privacy, efficiency, and scalability. DWNs are gived up on global consensus and state.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  DWN offers a permission layer out of the box. The user has control and complete control of access rights.&lt;/li&gt;
&lt;li&gt;  DWN is network agnostic, so you don’t need to trust any network or organization that stays behind a network or protocol&lt;/li&gt;
&lt;li&gt;  DWN is transport agnostic and could be used in heterogeneous setup&lt;/li&gt;
&lt;li&gt;  DWN has a self-hosting and embeddable setup, so your decentralized app could start with zero-cost&lt;/li&gt;
&lt;li&gt;  DWN still has an incentives challenge, and it is one of the topics that should be solved by the community and TBD folks. I believe that it will be a network of hosted DWNs in the future&lt;/li&gt;
&lt;li&gt;  Most importantly, DWN as a protocol-based solution open to extension and, on top of itself, allows to build of flexible and secured data protocols that unlock user data and made them interoperable&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Building for the Future
&lt;/h2&gt;

&lt;p&gt;Moving forward, we should focus on creating products that genuinely enhance people’s lives while respecting their privacy and data sovereignty. It’s not just about selling a technology; it’s about integrating it meaningfully into the fabric of daily life. This approach will drive actual adoption and appreciation of SSI and related technologies.&lt;/p&gt;

&lt;p&gt;Join us on this journey, try our products, and be part of a community that values privacy, security, and practical innovation. Here’s to a year of meaningful technological advancements and a future where technology serves humanity profoundly and respectfully.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>DWNs as a data game changer for sovereign data</title>
      <dc:creator>Volodymyr Pavlyshyn</dc:creator>
      <pubDate>Sun, 05 Nov 2023 19:46:51 +0000</pubDate>
      <link>https://dev.to/volland/dwns-as-a-data-game-changer-for-sovereign-data-3iec</link>
      <guid>https://dev.to/volland/dwns-as-a-data-game-changer-for-sovereign-data-3iec</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/OvpXde1SGIk"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Earlier days of SSI.  Is everything a VC?
&lt;/h2&gt;

&lt;p&gt;It was a boom of self-sovereign identity projects around 2018-2020. All of them had one common bias. Everything was viewed as a Verifiable Credential. So, every single user data point should be represented as a W3C verifiable credential or similar technology. If you have a hammer, everything is a nail that didn't work well. &lt;br&gt;
The majority of user data is not vcfiable . VCfication makes sense for data points with an attestation component that needs to be verifiable by a third party and creates a need for classical trust triangle interaction. &lt;br&gt;
So, we must admit that sovereign data is much broader than a VC. We still need to share user data concerning SSI principles of user-centricity and consent. &lt;br&gt;
Now we need a persistent and application layer that enable this polyglot data setup &lt;/p&gt;

&lt;h2&gt;
  
  
  Missed persistence layer
&lt;/h2&gt;

&lt;p&gt;Self-sovereign Identity has the bold goal of creating a missed identity layer for the Internet. It is more than one problem of the web. Internet was designed on top of stateless protocols, and all these protocols miss decentralized persistence. So even for Verifiable Credentials and Identity data like DID documents, you need persistence, and to satisfy the SSI idea, you probably need it in a decentralized manner. &lt;/p&gt;

&lt;h2&gt;
  
  
  IPFS is not a rescue
&lt;/h2&gt;

&lt;p&gt;IPFS was a pioneer of decentralized data storage outside of blockchain. IPFS focuses on self-addressable data, shapes a decentralized application, and enables a lot of Dapps. IPFS struggle on a few areas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;privacy&lt;/strong&gt; : all data is open and accessible for everyone, like most blockchains. So to be private only one way is a full encryption better if you use a post-quantum driven encryption as far as IPFS has a promise of immutable data storage where data stay forever&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Incentives&lt;/strong&gt; - the way much bigger problem is how to convince node maintainers to store your data and replicate your data ? If you have no nodes - you data is gone. Blockchain have implicit economic model &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;heavy&lt;/strong&gt; - it is almost impossible to run ipfs on local device mode. 
&amp;gt; For a general IPFS system, not accounting for specific workload requirements or use cases, high core count processors and a minimum of 32GB of memory is recommended. A tiered storage system using NVMe, SSD, and HDD devices is ideal for data storage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;global&lt;/strong&gt; is designed as a decentralized global storage &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;peer-to-peer&lt;/strong&gt; nature forces users to install and use a client for data access, limiting adoption and setting a relatively high technical barrier.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Ceramic like services
&lt;/h2&gt;

&lt;p&gt;Ceramic take IPFS to the next level and for sure fix privacy concern with lit protocol and solve Incentive problem in some way. However, the network is private, permission-based, and controlled by a private company. So we still not there &lt;/p&gt;

&lt;h2&gt;
  
  
  What kind of storage do we need for sovereign data?
&lt;/h2&gt;

&lt;p&gt;So, what does an excellent persistent layer for sovereign data look like? &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Content polyglot layer&lt;/strong&gt;: To empower and enable wallets, it should be capable of storing VCs and other structured data like files, blobs, and other media.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;local first&lt;/strong&gt; and &lt;strong&gt;offline first&lt;/strong&gt; - The user should be able to self-host and own data in a perfect setup system that should be capable of running on user hardware &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;device and mobile friendly&lt;/strong&gt; - continuation of previous requirement. more and more users are mobile-first, or even more often, we have users that use mainly mobile &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;extendable in a decentralized manner&lt;/strong&gt; It is a question of time when the capacity of a mobile device will not be enough to handle all the data that the user wants to take with him. We wish to extend our local first model with decentralized and online capabilities &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secure&lt;/strong&gt; - we want edge encryption and optionally synchronize data. The user should decide what data to share and replicate with the decentralized node and other network users. Better to have client-side end-to-end encryption &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interoperable and open&lt;/strong&gt; storage should work over open standard data protocol and transparent and user-centric protocol-based data exchange&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;reactive and proactive&lt;/strong&gt; on a decentralized and data-intensive exchange, it is essential to have a more reactive and streaming approach to get data changes and keep devices in sync &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;findable&lt;/strong&gt; According to FAIR principles, data should not only be accessible and reusable but also friendly to discovery and recall&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;queryable&lt;/strong&gt; it should be a way to implement intelligent queries across structured data &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How does DWN fit into the game?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Content polyglot layer&lt;/strong&gt; DWN  suitable to store structures and binary data and potential files. The system expects self explainable data as far as you provide a data schema together with a data, and schema is one of the keys &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;local first&lt;/strong&gt; and &lt;strong&gt;offline first&lt;/strong&gt;  DWN reference implementation built on top of LevelDB and SQL-based setup is possible. User could use DWN server or use an app that has embedded DWN built with DWN SDK&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;extendable in a decentralized manner&lt;/strong&gt; DWN is built as a Relay based decentralized solution that is the sweet spot between a centralized server and peer-to-peer setup. On top of Relay, you can construct flexible topologies from self-hosted solo servers and in-memory or even browser-based agents to a full-scale sync data mesh system&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secure&lt;/strong&gt; DWN offers DID Auth layer and full-scale permission and data access management out of the box.  End to end  client side edge encryption is one of the out-of-the-box &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interoperable and open&lt;/strong&gt; DWN is an open protocol under the DIF foundation umbrella. DWN is fully open source and driven by a proactive and open community. DWN encourages a protocol and data protocol-driven development &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;reactive and proactive&lt;/strong&gt; DWN has a sync mechanism as the propagation mechanism currently on active development. DWN server offered socketcket interface. A pretty prominent feature is Hooks, which offer transport-agnostic subscriptions to data changes and event &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;findable&lt;/strong&gt; Currently Discovery of DWNs heavily depends on DID document and quite similar top a DIDComm v2 mechanism's &lt;/li&gt;
&lt;li&gt;- &lt;strong&gt;queryable&lt;/strong&gt; DWN is quite limited of queries and currently require external indexing and query solutions &lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>dwn</category>
      <category>web5</category>
      <category>tbd</category>
      <category>ssi</category>
    </item>
    <item>
      <title>What is WEB5 about, and why does it matter in the post-AI and post-blockchain world?</title>
      <dc:creator>Volodymyr Pavlyshyn</dc:creator>
      <pubDate>Sat, 09 Sep 2023 15:14:03 +0000</pubDate>
      <link>https://dev.to/volland/what-is-web5-about-and-why-does-it-matter-in-the-post-ai-and-post-blockchain-world-3a5n</link>
      <guid>https://dev.to/volland/what-is-web5-about-and-why-does-it-matter-in-the-post-ai-and-post-blockchain-world-3a5n</guid>
      <description>&lt;h2&gt;
  
  
  Ultimate challenges of modern WEB
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;internet was born without identity layer. So you dont know with whom you talk &lt;/li&gt;
&lt;li&gt;internet was born stateless. so it is allow to scale massively but how user could keep his data ?&lt;/li&gt;
&lt;li&gt;How to prove a data ownership and authentisity of data ?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why it is matter now for AI world?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://yakihonne.com/article/naddr1qq25cmm9g5c4qvjkxedrwertvsek7wz0ffg8xq3qu6qhg5ucu3xza4nlz94q90y720tr6l09avnq8y3yfp5qrv9v8susxpqqqp65wehdayu"&gt;AI future needs a data-driven pseudo-anonymous Identity.&lt;/a&gt;. AI will reshape a landscape completelly. We will need a way to identify original content form a generated one. Data is a main fuel of AI models. Research show that evem smaller models perform better on quality data. it is opens topic of data economy and data ownership. Even more now we extending owr self with a agent - now we need to manage agent identities and payments for interconected agents network. All this require new ways of managing identity and data ownership&lt;/p&gt;

&lt;h2&gt;
  
  
  WEB3 give you Assets to own but ...
&lt;/h2&gt;

&lt;p&gt;We all know about web3 and blockchain together with a programmable economy and tokenisation of assets. Web3 was invented as a concept by Dr.Gavin Wood from Ethereum blockchain to sell a idea of smart contracts and etherium network. The biggest value of this movement was a ownership. First time we got a mechanism to give a user digitalised assets that user could own together with it we faced with a problem of identity in a decentralized world.&lt;br&gt;
To get deeper historical and technological read my article &lt;a href="https://yakihonne.com/article/naddr1qq2kwu2jdfux5s6nfa3hjajev43x5h65d9jrjq3qu6qhg5ucu3xza4nlz94q90y720tr6l09avnq8y3yfp5qrv9v8susxpqqqp65wt32put"&gt;Pre Web , Web1, Web2 , web3 , web5 , web7 and all hundreds of future web X explained in 12 Toots&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Challanges of WEB3
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Every body has his own view on web3 future and his own set of challenges &lt;/li&gt;
&lt;li&gt;Privacy is broken and now we have a tornado and all Layer 2 / layer 3 patches that broke a ladger concept &lt;/li&gt;
&lt;li&gt;User is locked in a particular blockchain and practically has no way of interacting ouside of network &lt;/li&gt;
&lt;li&gt;Networks of Networks - only one god know how many of blockchains and crypto currency procects we have nowadays &lt;/li&gt;
&lt;li&gt;data persistence is limited and expencive &lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Web 3 and second system syndrome
&lt;/h3&gt;

&lt;p&gt;We have so many requirements and features for the next web version that we failed to deliver it and got lost.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Internet for machines and semantic web&lt;/li&gt;
&lt;li&gt;internet of connected data&lt;/li&gt;
&lt;li&gt;internet of IoT devices and things&lt;/li&gt;
&lt;li&gt;Internet of identity and ownership and most recent challenge Internet of AI-powered agent Satohi paper and Vitalic Buterin idea of intelligent contracts bring a new view of ownership and economy but ignore heavenly privacy , ownership, and data.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Web3 locks a user in a new glass cage
&lt;/h3&gt;

&lt;p&gt;Blockchain is a promise of WEB3 and a new era of internet lock users in even more restricted and isolated networks that force to be self-contained and accumulate mainly public data inside a network with highly hight cost storage and require the cost of interaction. Another challenge is a speed of transation - blockchains are slow. So blockchain is cool for assets and a new economy but fail to create a identity and new social space for extended human and machines.&lt;/p&gt;
&lt;h2&gt;
  
  
  WEB5 build on top of Self Sovreign Identity
&lt;/h2&gt;

&lt;p&gt;For SSI read my article &lt;a href="https://yakihonne.com/article/naddr1qq25cuj8wpn97j22f9nhgampverrge6wx9f9yq3qu6qhg5ucu3xza4nlz94q90y720tr6l09avnq8y3yfp5qrv9v8susxpqqqp65wee5tj6"&gt;Self Sovereign Identity in 7 Toots&lt;/a&gt; . Idea is simple - we build a &lt;strong&gt;missed identity layer&lt;/strong&gt; that treat humans as something more that a private key and give a tools to create a data point about ourselves and others and freally exchange this data via protocols. We unlock a user for a glass cage of blockchain and from a fragmented nightmare of web2 platforms and apps where you slice yourself to hundreds of you. Now  holistic you open to the world&lt;/p&gt;
&lt;h3&gt;
  
  
  Building Blocks of WEB5
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Identity layer on top of SSI tools - DIDs&lt;/li&gt;
&lt;li&gt;missed decentralized persistence layer with a permissions and synchronisation on top of DWN&lt;/li&gt;
&lt;li&gt;Verifiable and Owned data with a Verifiable Credentials &lt;/li&gt;
&lt;li&gt;DApps on top of DWNs 
### Old WEB3 &amp;amp; SSI Tools
#### Keys
&lt;strong&gt;Asymmetric Keys + Signatures&lt;/strong&gt; — backbone of decentralized identity in #web3 and #web5 that give #algorithmic #cryptographical basics of identity. But while we not locked to a network that create addressable space we have a new challenge - How to distribute and manage Public Keys so we have a need of DPKI - decentralized Public Key Infrastructure &lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  DIDs
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;DID give Decentralized Public Key Infrastructure&lt;/strong&gt; that distributes your Public Keys and service endpoints to a broader audience. &lt;/p&gt;

&lt;p&gt;DID is a core of SSI and create cryptographic verifieble, decentralised, resolvable identifier. Decentralized Identifier (DID) is a unique, persistent, and cryptographically verifiable identifier that allows individuals, organizations, or devices to establish and manage their digital identities independently. DIDs are used in decentralized identity systems, enabling users to have control over their data and interact securely without relying on a centralized authority.&lt;/p&gt;
&lt;h5&gt;
  
  
  DID Identifier
&lt;/h5&gt;

&lt;p&gt;Representation of did itself. is a part of DID URI.&lt;/p&gt;

&lt;p&gt;did:key identifier&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0UxbSxzu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/format:webp/1%2AQ-yQXBFuuFIEZIjADkinVw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0UxbSxzu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/format:webp/1%2AQ-yQXBFuuFIEZIjADkinVw.png" alt="" width="800" height="138"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h5&gt;
  
  
  DID Document
&lt;/h5&gt;

&lt;p&gt;A DID (Decentralized Identifier) document is a structured, machine-readable JSON or JSON-LD document that contains essential information associated with a specific DID. It serves as a "public profile" for a decentralized identity, providing the necessary details for verifying signatures, encrypting/decrypting messages, and interacting with the identity's associated services.&lt;/p&gt;

&lt;p&gt;The DID document typically includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The DID itself: A unique identifier that represents the decentralized identity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Public keys: One or more public keys associated with the DID, used for cryptographic operations such as verifying signatures and encrypting messages.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Authentication methods: Mechanisms to prove control of the DID, which typically involve the use of public keys.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Service endpoints: URLs or other identifiers of services related to the DID, such as profile information, communication channels, or data repositories.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Other metadata: Additional information related to the DID, such as timestamps, controller information, or specific DID method details.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The DID document’s information allows other parties to trust and interact securely with the associated DID without relying on a centralized authority. DID documents are created, updated, and deactivated according to the rules and processes defined by the DID method associated with the DID. They are usually stored on distributed ledgers, blockchains, or other decentralized networks, making them globally resolvable and cryptographically verifiable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "@context": "https://w3id.org/security/v2",
  "publicKey": [
    {
      "id": "did:elem:EiBa0KyUWgvMdkt_ywullSPac2kyOkRP5JRtHSeICQ1t6Q#primary",
      "usage": "signing",
      "type": "Secp256k1VerificationKey2018",
      "publicKeyHex": "022ca63fffbd8b6dd7e54fa88b76d5245700ac81657fd59a03b73e4325ba1e19ba"
    },
    {
      "id": "did:elem:EiBa0KyUWgvMdkt_ywullSPac2kyOkRP5JRtHSeICQ1t6Q#recovery",
      "usage": "recovery",
      "type": "Secp256k1VerificationKey2018",
      "publicKeyHex": "0390d67bfbfc80d00edc7080a4c91f1c844208fabd03e158a5910f5d1601e69eb5"
    }
  ],
  "authentication": [
    "did:elem:EiBa0KyUWgvMdkt_ywullSPac2kyOkRP5JRtHSeICQ1t6Q#primary"
  ],
  "assertionMethod": [
    "did:elem:EiBa0KyUWgvMdkt_ywullSPac2kyOkRP5JRtHSeICQ1t6Q#primary"
  ],
  "id": "did:elem:EiBa0KyUWgvMdkt_ywullSPac2kyOkRP5JRtHSeICQ1t6Q"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  DID Actions
&lt;/h4&gt;

&lt;p&gt;It is four posible DID Actions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Creating a DID&lt;/strong&gt;: Generating a new identifier and associating it with a DID document, which contains public key material and service endpoints for the identity. For DIDs on blockchaine we could see term &lt;strong&gt;Anhoring&lt;/strong&gt;. DID anchoring refers to the process of registering a Decentralized Identifier (DID) and its associated DID document on a distributed ledger or blockchain. Anchoring provides a secure, tamper-proof, and verifiable record of the DID’s existence and its associated information, making it an essential component of decentralized identity systems.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Resolving a DID&lt;/strong&gt;: Retrieving the DID document associated with a specific DID, which is essential for verifying signatures, encrypting/decrypting messages, and interacting with the identity’s associated services.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Updating a DID&lt;/strong&gt;: Modifying the DID document, such as adding or updating public keys, service endpoints, or other metadata. This action typically requires authorization from the DID controller.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Deactivating a DID&lt;/strong&gt;: Marking a DID as inactive, rendering it unusable for future interactions. This action also usually requires authorization from the DID controller. DID resolution is a main and mandatory operations. Every did method has create procedure.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  DID method
&lt;/h4&gt;

&lt;p&gt;Method is concrete implementation that defines the rules and processes for did actions on a particular distributed ledger, blockchain, or other decentralized network. DID methods provide a standardized way to manage DIDs and their associated DID documents, enabling interoperability between different decentralized identity systems. Each DID method is identified by a unique method name, which appears in the DID itself. For example, a DID with the method name “example” would look like “did:&lt;strong&gt;example&lt;/strong&gt;:123456789abcdefghi”.&lt;/p&gt;

&lt;p&gt;ould change an owner and be sold or reasigned&lt;/p&gt;

&lt;h4&gt;
  
  
  DID Relations demistified
&lt;/h4&gt;

&lt;p&gt;Relations between all parts of DID identifier can be illustrated in the following diagram. DID method dictate how DID identifier gets created, updated, deactivated, and resolved.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YR8tp28P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1064/1%2AccyyKkG4pIOB47Mi6BNGYw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YR8tp28P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1064/1%2AccyyKkG4pIOB47Mi6BNGYw.png" alt="" width="532" height="553"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://yakihonne.com/article/naddr1qq2k7mmpgvm8vu3dt9e4qdj9fe3xc32nfdd8gq3qu6qhg5ucu3xza4nlz94q90y720tr6l09avnq8y3yfp5qrv9v8susxpqqqp65wt8g4j3"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  DWN - game changer in a data
&lt;/h3&gt;

&lt;p&gt;DWN = Secured storage + message relay. &lt;br&gt;
Yep it is some how similar to noster relays but focused not a social media but data and data exchanges. It is more complex because it should be more generic and allow you to describe complex data and data interactions. Thats why DWN as a protocol allows you to describe your own protocols around a data &lt;/p&gt;

&lt;p&gt;Protocol-based on messages, but it is not about messages at all. Messages only transfer data about Records, Permissions, Hooks, and Protocols.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--J9LDnb1E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/1%2AO8JDV7lX8IyrQ6MeoDaiwA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--J9LDnb1E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/1%2AO8JDV7lX8IyrQ6MeoDaiwA.png" alt="" width="800" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;DWN is a stack of Access and data Protocols.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hjd6I_VL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/1%2A9jisklXWpJdo2wMyP9FY6g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hjd6I_VL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/1%2A9jisklXWpJdo2wMyP9FY6g.png" alt="" width="800" height="414"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Key Concepts and Interfaces&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--31hc8Npo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1392/1%2AorZx2RFt--uqOVW-DQh7Kw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--31hc8Npo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1392/1%2AorZx2RFt--uqOVW-DQh7Kw.png" alt="" width="696" height="528"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Schema&lt;/strong&gt; — the core of interoperability defines a data context and meaning.&lt;br&gt;
&lt;strong&gt;Records&lt;/strong&gt; - the interface of Decentralized Web Nodes provides a mechanism to store data relative to shared schemas.&lt;br&gt;
&lt;strong&gt;Permissions&lt;/strong&gt; — provides a mechanism for external entities to request access to various data and functionality. It employs a capabilities-based architecture that allows for DID-based authorization and delegation of authorized capabilities to others if permitted by the owner of a Decentralized Web Node.&lt;br&gt;
&lt;strong&gt;Protocols&lt;/strong&gt; — introduces a mechanism for declaratively encoding an app or service’s underlying protocol rules, including segmentation of records, relationships between records, data-level requirements, and constraints on how participants interact with a protocol. With the DWeb Node Protocols mechanism, one can model the underpinning protocols for a vast array of use cases in a way that enables interop-by-default between app implementations that ride on top of them.&lt;br&gt;
&lt;strong&gt;Hooks&lt;/strong&gt; — aim to not only allow permissioned subscribers to be notified of new data but also optionally respond to the entity’s request that triggers their invocation. This allows a subscribed entity to process the data and react to the entity waiting on results.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://yakihonne.com/article/naddr1qqyrvdecxsmxvvtpqgswdqt52wvwgnpw6el3z6szhj09843a0hj7kfsrjgjys6qpkzkrcwgrqsqqqa280fvggc"&gt;Read in more datail&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Verifiable Data
&lt;/h3&gt;

&lt;p&gt;Verifiable credentials allow you to share information about yourself and others in a temper-proof and end-verifiable way. VC contains the issuer’s signature, a person, and an organization that creates a data statement. critical part it is based on &lt;a href="https://www.w3.org/TR/vc-data-model-2.0/"&gt;open standards&lt;/a&gt; &lt;/p&gt;


&lt;h4&gt;
  
  
  Anatomy Of VC
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;machine readable data context for semantic web and AI&lt;/li&gt;
&lt;li&gt;data &lt;/li&gt;
&lt;li&gt;optional schema &lt;/li&gt;
&lt;li&gt;optional revocation data &lt;/li&gt;
&lt;li&gt;optional expiration data &lt;/li&gt;
&lt;li&gt;signature &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;VC = data + metadata + signature &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0knERrZk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.w3.org/TR/vc-data-model-2.0/diagrams/vc.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0knERrZk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.w3.org/TR/vc-data-model-2.0/diagrams/vc.svg" alt="" width="325" height="240"&gt;&lt;/a&gt;&lt;br&gt;
Example of Revocable VC&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  '@context': [
    'https://www.w3.org/2018/credentials/v1',
    'https://schema.affinidi.com/ContentLikeV1-0.jsonld',
    'https://w3id.org/vc-revocation-list-2020/v1'
  ],
  id: 'claimId:i2wgld5x7b',
  type: [ 'VerifiableCredential', 'ContentLike' ],
  holder: {
    id: 'did:elem:EiAs9VqvNcEMkm9OfMdseWR0jMIltWHuUd5tCK_f17M6jA;elem:initial-state=eyJwcm90ZWN0ZWQiOiJleUp2Y0dWeVlYUnBiMjRpT2lKamNtVmhkR1VpTENKcmFXUWlPaUlqY0hKcGJXRnllU0lzSW1Gc1p5STZJa1ZUTWpVMlN5SjkiLCJwYXlsb2FkIjoiZXlKQVkyOXVkR1Y0ZENJNkltaDBkSEJ6T2k4dmR6TnBaQzV2Y21jdmMyVmpkWEpwZEhrdmRqSWlMQ0p3ZFdKc2FXTkxaWGtpT2x0N0ltbGtJam9pSTNCeWFXMWhjbmtpTENKMWMyRm5aU0k2SW5OcFoyNXBibWNpTENKMGVYQmxJam9pVTJWamNESTFObXN4Vm1WeWFXWnBZMkYwYVc5dVMyVjVNakF4T0NJc0luQjFZbXhwWTB0bGVVaGxlQ0k2SWpBek5UUXhZMk01T1RabU56VmxaR1U1WkRnd00yVXlOVE5oTm1FNU5UWXdOekF5TWprMk1EaGhNemM0WVRWbE56RmlaV1V4WldGaE1EQXpObU0zTkdJME1DSjlMSHNpYVdRaU9pSWpjbVZqYjNabGNua2lMQ0oxYzJGblpTSTZJbkpsWTI5MlpYSjVJaXdpZEhsd1pTSTZJbE5sWTNBeU5UWnJNVlpsY21sbWFXTmhkR2x2Ymt0bGVUSXdNVGdpTENKd2RXSnNhV05MWlhsSVpYZ2lPaUl3TTJOaU1qZzFPVGRrWkRjM016bG1OREl3WTJaaVpEUXdOekZtTUdNNU5Ua3dPRFZtWVRBNVlqSXlOR1l4Tm1ZeE1UbGlOelV6WVRZeVpXVTJaalJqT1RRaWZWMHNJbUYxZEdobGJuUnBZMkYwYVc5dUlqcGJJaU53Y21sdFlYSjVJbDBzSW1GemMyVnlkR2x2YmsxbGRHaHZaQ0k2V3lJamNISnBiV0Z5ZVNKZGZRIiwic2lnbmF0dXJlIjoiOXg1UVpYS0h4OEFCSmd2cmhqVFhhR2NGUC1TSVdoYVJCeW1Vbm9vOGk2dGdMaDhWSnlWWGxnbS0xaTZqSXROTW1NZXEwX2t1SUZRZnVNelVNdVNMbXcifQ'
  },
  credentialSubject: {
    data: {
      '@type': [Array],
      url: 'https://www.youtube.com/watch?v=owbkzvLhblk',
      date: '2022-09-09T13:22:20.668Z',
      like: true,
      score: 10
    }
  },
  credentialSchema: {
    id: 'https://schema.affinidi.com/ContentLikeV1-0.json',
    type: 'JsonSchemaValidator2018'
  },
  issuanceDate: '2022-09-09T13:22:20.668Z',
  expirationDate: '2065-09-10T00:00:00.000Z',
  credentialStatus: {
    id: 'https://revocation-api.prod.affinity-project.org/api/v1/revocation/revocation-list-2020-credentials/did:elem:EiBIkVawTQOfOCYp2xSITNKKePuELFTj3oc1ITnxk2uehw/20551#1',
    type: 'RevocationList2020Status',
    revocationListIndex: '1',
    revocationListCredential: 'https://revocation-api.prod.affinity-project.org/api/v1/revocation/revocation-list-2020-credentials/did:elem:EiBIkVawTQOfOCYp2xSITNKKePuELFTj3oc1ITnxk2uehw/20551'
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://www.w3.org/TR/vc-data-model-2.0/"&gt;Spec&lt;/a&gt;&lt;br&gt;
NOSTR events is verifiable data too as far as it is signed &lt;/p&gt;

&lt;h3&gt;
  
  
  DApps - How it is work all together
&lt;/h3&gt;

&lt;p&gt;It is simirar to a WEB3 Dapp but istead of blockchain it is connected to a several DWNs that manage and store a data of application or particular user represented by DIDs. Web5 Dapps designed more for human interaction gateways that give you a UI and etc. For a agent to agent or wallet to wallet interactions DWNs and message interfaces is used together with application level protocols.&lt;/p&gt;

&lt;h3&gt;
  
  
  To summarize
&lt;/h3&gt;

&lt;p&gt;Web5 give identity and persistent layers missed by web in a network agnostic maner.&lt;br&gt;
It could work on top of regular network protocols or colocal&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DID - give you a destribution of Public identity that are network independent &lt;/li&gt;
&lt;li&gt;DWNs - give a persistent and intyeraction layer &lt;/li&gt;
&lt;li&gt;DWNs protocols - allow to define Dapps data exchange logic &lt;/li&gt;
&lt;li&gt;VCs allow to add ownnership and authentisity of data and build data and agent economy on top of it &lt;/li&gt;
&lt;li&gt;Dapps - use all this tools to interact with a human in a loop. Serve a UI and interact with a DWNs and agents
&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Targeted Personal Knowledge Graphs in Professional Networks. From Hunters to DAO and beyond</title>
      <dc:creator>Volodymyr Pavlyshyn</dc:creator>
      <pubDate>Fri, 01 Sep 2023 11:48:31 +0000</pubDate>
      <link>https://dev.to/volland/targeted-personal-knowledge-graphs-in-professional-networks-from-hunters-to-dao-and-beyond-47nl</link>
      <guid>https://dev.to/volland/targeted-personal-knowledge-graphs-in-professional-networks-from-hunters-to-dao-and-beyond-47nl</guid>
      <description>&lt;p&gt;Nostr is about Social Networks. What came first to your mind when we mention social Network? A lot of folks compare NOSTR-based apps with Twitter, but Twitter is a far away from a social movement.&lt;br&gt;
The biggest social network of mine is not Twitter or Mastodon. nop even not facebook. It is LinkedIN&lt;/p&gt;

&lt;h2&gt;
  
  
  It is not about Twitter
&lt;/h2&gt;

&lt;p&gt;Twitter was launched around 2006, but before it was.&lt;br&gt;
SixDegrees.com (1997): As mentioned, it was the first to allow users to create profiles and friend lists.&lt;/p&gt;

&lt;p&gt;LiveJournal (1999): Allowed users to keep a blog, journal, or diary and also make connections.&lt;/p&gt;

&lt;p&gt;Friendster (2002): One of the first to use the term "social network," it allowed users to connect with friends, post pictures, and share content.&lt;/p&gt;

&lt;p&gt;Hi5 (2003): Popular in Latin America and Southeast Asia, it allowed users to create profiles, connect with friends, and share photos and videos.&lt;/p&gt;

&lt;p&gt;LinkedIn (2003): Focused on professional networking, it allowed users to connect with colleagues and other professionals.&lt;/p&gt;

&lt;p&gt;MySpace (2003): Allowed users to create profiles, have a list of friends, and share music and other media. It was particularly popular among musicians and artists.&lt;/p&gt;

&lt;p&gt;Orkut (2004): Developed by Google, it was popular in Brazil and India.&lt;/p&gt;

&lt;p&gt;Facebook (2004): Initially limited to Harvard students, it quickly expanded and became the dominant social network.&lt;/p&gt;

&lt;p&gt;I was earlier adopter of a Live Journal  and always was about a long-form content.&lt;/p&gt;

&lt;h2&gt;
  
  
  Future of targeted social networks
&lt;/h2&gt;

&lt;p&gt;On targeted, i mean social network of people with a common interest and goals with some passion and topics that unite them or maybe it is a place where you could find folks that were extreamly hard to find in a facebook like posts with food , cats, and boobs.&lt;br&gt;
First sucessful and long lived targeted social network for me wa LinkedIn&lt;/p&gt;

&lt;p&gt;From Hunters , Middle Ages, Guilds to LinkedIn and DAO&lt;br&gt;
People get together around profession and mastery from earlier beginning. I think hunters was the first tribal guild )). It is not only about a job search it is also about mastery of skills and proud and status and showing who you are.&lt;br&gt;
I know a lot of folks have linkedIn but root of problems there is not a topic of social media it is more around corporate culture that heavily shaped social media. It should be different.&lt;/p&gt;

&lt;h2&gt;
  
  
  Linkedin got Evil?!
&lt;/h2&gt;

&lt;p&gt;It is a classical story. The project was started with good intentions and goals, but it is somebody else business that is eager to make money.&lt;br&gt;
In general, it is a 2 simple strategies&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;lock users data in a platform&lt;/li&gt;
&lt;li&gt;Limit access to this data and make money on top of it. Now millions of profiles are locked in prison with limits to connect and search. Recruiters struggle the most. if linkedin kill you profile it is practically the end of your entire recruiter career.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  I am not looking for a job
&lt;/h2&gt;

&lt;p&gt;Nowadays, we have industries and professions that depend completely on platforms like Linked In because we haven't invented a Google for people or let's say google for professionals and the best that we have is LinkedIn, Xing, Monster, Stepstone focus on the broken idea of a job search. Your job is a subset of your activities, skills and interests. I am a YouTuber and nostr enthusiast that keen on decentralized tech and open technology and open source. I am a tea lover and keen on cognitive science, psychology and philosophy and all these stills and interests contribute to my professional profile and form my bubbles of people.&lt;br&gt;
I am looking for&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;people&lt;/li&gt;
&lt;li&gt;interesting challenges&lt;/li&gt;
&lt;li&gt;Confirmation of my skill&lt;/li&gt;
&lt;li&gt;confirmation of my knowledge and achievements from a network&lt;/li&gt;
&lt;li&gt;verifiable skills 
I do not want to go to yet another interview in my life. Big dream - i give you my profile based on a verified data point, and we could chat about our common values. I tried to prove that I knew JS or design patterns over and over and over again.
It is not about content, it is about relation !!
We don't see a forest among the trees...&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Targeted Social Graph
&lt;/h1&gt;

&lt;p&gt;We over-focused on content, but the real asset of social media that is often misunderstood by people is a social graph. Your connections matter a lot. Your connections and audience could say more about you than your content. We simply do not have tools today that allow to express our connections in a meaningful way. On Linked In, you have the option to connect or follow, but human relations is way more complex even in professional areas. it is all about portable social Graphics and portable audiences. Work relations or skill relations is more about what you do for others.&lt;br&gt;
Interoperability is a cornerstone of any protocol so we need to find a way to describe our relations in interoperablele way . Semantic web made a few attempts to do&lt;/p&gt;

&lt;h2&gt;
  
  
  "Friend of Friends" (FoF)
&lt;/h2&gt;

&lt;p&gt;First try to make a portable social graph was made by semantic web folks. In a semantic web we have a concept of anthology.&lt;br&gt;
An ontology is essentially a formal specification of a conceptualization. In simpler terms, it's a way to define the types, properties, and interrelationships of the entities that exist for a particular domain. In the context of the semantic web, ontologies are often expressed in languages like RDF (Resource Description Framework), OWL (Web Ontology Language), or Turtle.&lt;br&gt;
The concept of a "Friend of Friends" (FoF) ontology is often used in the context of semantic web technologies, social networking, and data modeling. The idea is to create a structured representation of social networks, where relationships like "friendship" can be formally defined and queried. This is particularly useful for applications that require a deep understanding of social connections, such as recommendation systems, targeted advertising, or social analytics.&lt;br&gt;
Problem hear - we have limited relation descriptions so you simply mimic i know this person link&lt;/p&gt;

&lt;h2&gt;
  
  
  "Description of a Career" (DOAC) and Resume RDF
&lt;/h2&gt;

&lt;p&gt;"Description of a Career" (DOAC) ontology, the focus would be on capturing various aspects of an individual's professional life. This could include:&lt;/p&gt;

&lt;p&gt;Basic Information: Name, contact details, and other personal identifiers.&lt;br&gt;
Skills: A list of skills the individual possesses, possibly categorized by domain (e.g., programming, management).&lt;br&gt;
Qualifications: Academic background, certifications, and other formal qualifications.&lt;br&gt;
Work Experience: Past roles, responsibilities, and achievements.&lt;br&gt;
Projects: Specific projects worked on, along with the role played and technologies used.&lt;br&gt;
Endorsements: Recommendations or endorsements from colleagues, supervisors, or other professional contacts.&lt;br&gt;
Goals: Career objectives and future plans.&lt;br&gt;
We are still not there&lt;br&gt;
Resume RDF do a similar job but still does pure job in a space of relations. Some ontologies define your work relations in terms of organization structure. We need relations in the context of skills and what person do. Like we made a web3 app together. We run a cool event etc. Something that gives understanding of what you do for other people with other people&lt;/p&gt;

&lt;h2&gt;
  
  
  NOSTR Context
&lt;/h2&gt;

&lt;p&gt;Nostr has one big supper power - All events are signed. It means it is an end verifiable, immutable, and temper proof. We almost there we already have a backbone of social features that could be enriched by more powerful relations&lt;/p&gt;

&lt;h3&gt;
  
  
  NOSTR missed social graph features
&lt;/h3&gt;

&lt;p&gt;Now you see a problem. A list of followers is not enough. We need to find together a better way to describe an interaction experience with other people in the context of skills, knowledge, interests, and what they do for the community and us.&lt;br&gt;
Don't be a stranger! You could tell much more about your relation to a person.&lt;/p&gt;

&lt;h2&gt;
  
  
  NOSTR missed events
&lt;/h2&gt;

&lt;p&gt;As far as NOSTR protocol go with a idea of kinds of events it is turn to a hard path of extending a protocol with particular human activities.&lt;br&gt;
One area is a people's lifetime events&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;job or project&lt;/li&gt;
&lt;li&gt;achievement &lt;/li&gt;
&lt;li&gt;Completion of task for DAO&lt;/li&gt;
&lt;li&gt;skill and skill recommendation &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One more potential feature - maybe I want to follow selective events from a person only related to some types of activities&lt;/p&gt;

&lt;h2&gt;
  
  
  The DAO friendly
&lt;/h2&gt;

&lt;p&gt;DAO will change the way we work in the near future. For some of my friends, it is already a reality. It is hard to build a reputation in a highly anonymous environment.  I see a big undiscovered potential of Target Social Graphs powered by NOSTR for a talent and partners search. But it will be a topic for next article&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Holistic Identity, Digital Twins, and Autonomous Agents: A New Era of Self-Sovereign Identity</title>
      <dc:creator>Volodymyr Pavlyshyn</dc:creator>
      <pubDate>Sun, 30 Jul 2023 09:53:42 +0000</pubDate>
      <link>https://dev.to/volland/holistic-identity-digital-twins-and-autonomous-agents-a-new-era-of-self-sovereign-identity-ee6</link>
      <guid>https://dev.to/volland/holistic-identity-digital-twins-and-autonomous-agents-a-new-era-of-self-sovereign-identity-ee6</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/oqDxoAbethk"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;In the digital age, our identities are fragmented across various platforms, each holding a piece of our data. This fragmentation poses a significant challenge, as it prevents us from having a complete, unified view of our own digital identities. However, the concept of a holistic identity, digital twins, and autonomous agents can offer a solution to this problem, providing a more comprehensive and self-sovereign approach to digital identity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Holistic Identity: A Unified View of Self
&lt;/h2&gt;

&lt;p&gt;Holistic identity is not just a technical term; it's a philosophical concept that aims to solve the problem of data fragmentation. Unlike traditional identity systems that are authoritative and siloed, a holistic identity provides a unified view of an individual's data across various platforms. &lt;/p&gt;

&lt;p&gt;In essence, a holistic identity is a snapshot of all data points about you, including your behavior, activities, and posts. It's not just about an identifier or login password; it's about aggregating all the data points that identify you, providing a more comprehensive view of your digital self.&lt;/p&gt;

&lt;h2&gt;
  
  
  Digital Twins: Your Digital Copy
&lt;/h2&gt;

&lt;p&gt;A digital twin is a digital copy of you and all your data that you control. It's a continuation of your holistic identity, aggregating all the data points about you and all the data produced by you. &lt;/p&gt;

&lt;p&gt;The concept of a digital twin goes beyond just storing information; it's about getting benefits out of it. With a digital twin, you can interact with your data, gain insights, and even sell your data. It opens up a world of possibilities, from personalization to automation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Autonomous Agents: Your Digital Assistants
&lt;/h2&gt;

&lt;p&gt;Autonomous agents are the next step from digital twins. They are essentially digital assistants that can perform tasks on your behalf. These agents can have access to a portion of your data and can perform various operations, from booking tables and buying tickets to trading operations and data trading on data exchanges.&lt;/p&gt;

&lt;p&gt;Autonomous agents can analyze data from your digital twin and perform actions based on it. They can optimize routine tasks, cooperate with each other, create trust networks, and even make micro-payments. &lt;/p&gt;

&lt;h2&gt;
  
  
  The Future of Self-Sovereign Identity
&lt;/h2&gt;

&lt;p&gt;The concepts of holistic identity, digital twins, and autonomous agents are interlinked and form the cornerstone of a self-sovereign identity. They provide a way to have a sovereign persona and proof that the data belongs to you.&lt;/p&gt;

&lt;p&gt;These concepts are not just theoretical; they have practical applications that can revolutionize various domains, from healthcare and finance to personalization and automation. They represent the future of digital identity, a future where we have more control over our data and where our digital identities are unified, comprehensive, and self-sovereign.&lt;/p&gt;

&lt;p&gt;In conclusion, the era of self-sovereign identity is upon us. It's an era where we can control our data, gain insights from it, and use it to our advantage. It's an era where our digital identities are not fragmented across various platforms but are unified and comprehensive. It's an era where we can have digital twins and autonomous agents that can perform tasks on our behalf. It's an era of holistic identity, digital twins, and autonomous agents.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
