Integrating PostgreSQL Databases with ANF: Join this workshop to learn how to create a PostgreSQL server using Instaclustr’s managed service
Mobile Database Essentials: Assess data needs, storage requirements, and more when leveraging databases for cloud and edge applications.
Welcome to the Data Engineering category of DZone, where you will find all the information you need for AI/ML, big data, data, databases, and IoT. As you determine the first steps for new systems or reevaluate existing ones, you're going to require tools and resources to gather, store, and analyze data. The Zones within our Data Engineering category contain resources that will help you expertly navigate through the SDLC Analysis stage.
Artificial intelligence (AI) and machine learning (ML) are two fields that work together to create computer systems capable of perception, recognition, decision-making, and translation. Separately, AI is the ability for a computer system to mimic human intelligence through math and logic, and ML builds off AI by developing methods that "learn" through experience and do not require instruction. In the AI/ML Zone, you'll find resources ranging from tutorials to use cases that will help you navigate this rapidly growing field.
Big data comprises datasets that are massive, varied, complex, and can't be handled traditionally. Big data can include both structured and unstructured data, and it is often stored in data lakes or data warehouses. As organizations grow, big data becomes increasingly more crucial for gathering business insights and analytics. The Big Data Zone contains the resources you need for understanding data storage, data modeling, ELT, ETL, and more.
Data is at the core of software development. Think of it as information stored in anything from text documents and images to entire software programs, and these bits of information need to be processed, read, analyzed, stored, and transported throughout systems. In this Zone, you'll find resources covering the tools and strategies you need to handle data properly.
A database is a collection of structured data that is stored in a computer system, and it can be hosted on-premises or in the cloud. As databases are designed to enable easy access to data, our resources are compiled here for smooth browsing of everything you need to know from database management systems to database languages.
IoT, or the Internet of Things, is a technological field that makes it possible for users to connect devices and systems and exchange data over the internet. Through DZone's IoT resources, you'll learn about smart devices, sensors, networks, edge computing, and many other technologies — including those that are now part of the average person's daily life.
Enterprise AI
In recent years, artificial intelligence has become less of a buzzword and more of an adopted process across the enterprise. With that, there is a growing need to increase operational efficiency as customer demands arise. AI platforms have become increasingly more sophisticated, and there has become the need to establish guidelines and ownership. In DZone’s 2022 Enterprise AI Trend Report, we explore MLOps, explainability, and how to select the best AI platform for your business. We also share a tutorial on how to create a machine learning service using Spring Boot, and how to deploy AI with an event-driven platform. The goal of this Trend Report is to better inform the developer audience on practical tools and design paradigms, new technologies, and the overall operational impact of AI within the business. This is a technology space that's constantly shifting and evolving. As part of our December 2022 re-launch, we've added new articles pertaining to knowledge graphs, a solutions directory for popular AI tools, and more.
Revolutionizing Software Testing
Before diving into the specifics of prompt injections, let's first grasp an overview of LLM training and the essence of prompt engineering: Training Training Large Language Models (LLMs) is a nuanced, multi-stage endeavor. Two vital phases involved in LLM training are: Unsupervised Pre-Training LLMs are exposed to vast amounts of web-based data. They attempt to learn by predicting subsequent words in given sequences. This stored knowledge is encapsulated in the model's billions of parameters, similar to how smart keyboards forecast users' next words. Refinement via RLHF Despite pre-training providing LLMs with vast knowledge, there are shortcomings: They can't always apply or reason with their knowledge effectively. They might unintentionally disclose sensitive or private information. Addressing these issues involves training models with Reinforcement Learning using Human Feedback (RLHF). Here, models tackle diverse tasks across varied domains and generate answers. They're rewarded based on the alignment of their answers with human expectations — akin to giving a thumbs up or down for their generated content. This process ensures models' outputs align better with human preferences and reduces the risk of them divulging sensitive data. Inference and Prompt Engineering Users engage with LLMs by posing questions, and in turn, the model generates answers. These questions can range from simple to intricate. Within the domain of LLMs, such questions are termed "prompts." A prompt is essentially a directive or query presented to the model, prompting it to provide a specific response. Even a minor alteration in the prompt can lead to a significantly varied response from the model. Hence, perfecting the prompt often requires iterative experimentation. Prompt engineering encompasses the techniques and methods used to craft impactful prompts, ensuring LLMs yield the most pertinent, precise, and valuable outputs. This practice is crucial for harnessing the full capabilities of LLMs in real-world applications. How Are Prompts Used With LLM Applications In many applications, while the task remains consistent, the input for LLM varies. Typically, a foundational prompt is given to set the task's context before supplying the specific input for a response. For instance, imagine a web application designed to summarize the text in one line. Behind the scenes, a model might receive a prompt like: "Provide a one-line summary that encapsulates the essence of the input." Though this prompt remains unseen by users, it helps guide the model's response. Regardless of the domain of text users wish to summarize, this constant, unseen prompt ensures consistent output. Users interact with the application without needing knowledge of this backend prompt. Frequently, prompts can be intricate sets of instructions that require significant time and resources for companies to develop. Companies aim to keep these proprietary, as any disclosure could erode their competitive advantage. What Is Prompt Injection and Why Do We Care About It? It's crucial to understand from the earlier discussion that LLMs derive information from two primary avenues: The insights gained from the data during their training. The details provided within the prompt might include user-specific data like date of birth, location, or passwords. LLMs are usually expected not to disclose sensitive or private information or any content they're instructed against sharing. This includes not sharing the proprietary prompt as well. Considerable efforts have been made to ensure this, though it remains an ongoing challenge. Users often experiment with prompts, attempting to persuade the model into revealing information it's not supposed to disclose. This tactic of using prompt engineering to extract the outcome of what the developer unintended is termed "prompt injection." Here are some instances where prompt injections have gained attention: ChatGPT grandma hack became popular where a user could persuade the system to share Windows activation keys: Chat GPT Grandma Has FREE Windows Keys! — YouTube. Recently the Wall Street Journal has published an article on the same: With AI, Hackers Can Simply Talk Computers Into Misbehaving - WSJ. Example of indirect prompt injection through a web page: [Bring Sydney Back] Securing LLM Systems Against Prompt Injection | NVIDIA Technical Blog Google AI red team lead talks real-world attacks on ML • The Register Turning BingChat into Pirate: Prompt Injections are bad, mkay? (greshake.github.io) Points on Prompt Injection Attacks A prompt typically comprises several components: context, instruction, input data, and output format. Among these, user input emerges as a critical point susceptible to vulnerabilities and potential breaches. Hackers might exploit this by feeding the model with unstructured data or by subtly manipulating the prompt, employing key principles of prompting like inference, classification, extraction, transformation, expansion, and conversion. Even the provided input or output formats and model, particularly when used with certain plugins, can be tweaked using formats such as JSON, XML, HTML, or plain text. Such manipulations can compel the LLM to divulge confidential data or execute unintended actions. Depending on how the model is exploited, the AI industry classifies this spectrum of attacks as: Prompt Injection Prompt Leaking Token Smuggling Jailbreaking The image below highlights these prevalent security risk categories and illustrates that prompt hacking encompasses a broad spectrum of potential vulnerabilities and threats. Ways To Protect Yourself This domain is in a state of continuous evolution, and it is anticipated that within a few months, we will likely see more advanced methods for safeguarding against prompt hacking. In the interim, I've identified three prevalent approaches that individuals are employing for the same purpose. Learn Through Gamification Currently, Gandalf stands out as a popular tool that transforms the testing and learning of prompting skills into an engaging game. In this chat-based system, the objective is to uncover a secret password hidden within the system by interacting with it through prompts and posing questions. Twin LLM Approach The approach involves categorizing the model into two distinct groups: trusted or privileged models and untrusted or quarantined models. Learning is then restricted to occur exclusively from the trusted models, with no direct influence from prompts provided by untrusted users. Track and Authenticate the Accuracy of Prompts This requires detecting attacks happening in the Input and Output of the prompt. Rebuff provides an open-source framework for projection injection detection.
If you’re anything like me, you’ve noticed the massive boom in AI technology. It promises to disrupt not just software engineering but every industry. THEY’RE COMING FOR US!!! Just kidding ;P I’ve been bettering my understanding of what these tools are and how they work, and decided to create a tutorial series for web developers to learn how to incorporate AI technology into web apps. In this series, we’ll learn how to integrate OpenAI‘s AI services into an application built with Qwik, a JavaScript framework focused on the concept of resumability (this will be relevant to understand later). Here’s what the series outline looks like: Intro and Setup Your First AI Prompt Streaming Responses How Does AI Work Prompt Engineering AI-Generated Images Security and Reliability Deploying We’ll get into the specifics of OpenAI and Qwik where it makes sense, but I will mostly focus on general-purpose knowledge, tooling, and implementations that should apply to whatever framework or toolchain you are using. We’ll be working as closely to fundamentals as we can, and I’ll point out which parts are unique to this app. Here’s a little sneak preview. I thought it would be cool to build an app that takes two opponents and uses AI to determine who would win in a hypothetical fight. It provides some explanation and the option to create an AI-generated image. Sometimes the results come out a little wonky, but that’s what makes it fun. I hope you’re excited to get started because in this first post, we are mostly going to work on… Boilerplate :/ Prerequisites Before we start building anything, we have to cover a couple of prerequisites. Qwik is a JavaScript framework, so we will have to have Node.js (and NPM) installed. You can download the most recent version, but anything above version v16.8 should work. I’ll be using version 20. Next, we’ll also need an OpenAI account to have access to their API. At the end of the series, we will deploy our applications to a VPS (Virtual Private Server). The steps we follow should be the same regardless of what provider you choose. I’ll be using Akamai’s cloud computing services (formerly Linode). Setting Up the Qwik App Assuming we have the prerequisites out of the way, we can open a command line terminal and run the command: npm create qwik@latest. This will run the Qwik CLI that will help us bootstrap our application. It will ask you a series of configuration questions, and then generate the project for you. Here’s what my answers looked like: If everything works, open up the project and start exploring. Inside the project folder, you’ll notice some important files and folders: /src: Contains all application business logic /src/components: Contains reusable components to build our app with /src/routes: Responsible for Qwik’s file-based routing; Each folder represents a route (can be a page or API endpoint). To make a page, drop a index.{jsx|tsx} file in the route’s folder. /src/root.tsx: This file exports the root component responsible for generating the HTML document root. Start Development Qwik uses Vite as a bundler, which is convenient because Vite has a built-in development server. It supports running our application locally, and updating the browser when files change. To start the development server, we can open our project in a terminal and execute the command npm run dev. With the dev server running, you can open the browser and head to http://localhost:5173 and you should see a very basic app. Any time we make changes to our app, we should see those changes reflected almost immediately in the browser. Add Styling This project won’t focus too much on styling, so this section is totally optional if you want to do your own thing. To keep things simple, I’ll use Tailwind. The Qwik CLI makes it easy to add the necessary changes, by executing the terminal command, npm run qwik add. This will prompt you with several available Qwik plugins to choose from. You can use your arrow keys to move down to the Tailwind plugin and press Enter. Then it will show you the changes it will make to your codebase and ask for confirmation. As long as it looks good, you can hit Enter, once again. For my projects, I also like to have a consistent theme, so I keep a file in my GitHub to copy and paste styles from. Obviously, if you want your own theme, you can ignore this step, but if you want your project to look as amazing as mine, copy the styles from this file on GitHub into the /src/global.css file. You can replace the old styles, but leave the Tailwind directives in place. Prepare Homepage The last thing we’ll do today to get the project to a good starting point is make some changes to the homepage. This means making changes to /src/routes/index.tsx. By default, this file starts out with some very basic text and an example for modifying the HTML <head> by exporting a head variable. The changes I want to make include: Removing the head export Removing all text except the <h1>; Feel free to add your own page title text. Adding some Tailwind classes to center the content and make the <h1> larger Wrapping the content with a <main> tag to make it more semantic Adding Tailwind classes to the <main> tag to add some padding and center the contents These are all minor changes that aren’t strictly necessary, but I think they will provide a nice starting point for building out our app in the next post. Here’s what the file looks like after my changes. import { component$ } from "@builder.io/qwik"; export default component$(() => { return ( <main class="max-w-4xl mx-auto p-4"> <h1 class="text-6xl">Hi [wave emoji]</h1> </main> ); }); And in the browser, it looks like this: Conclusion That’s all we’ll cover today. Again, this post was mostly focused on getting the boilerplate stuff out of the way so that the next post can be dedicated to integrating OpenAI’s API into our project. With that in mind, I encourage you to take a moment to think about some AI app ideas that you might want to build. There will be a lot of flexibility for you to put your own spin on things. I’m excited to see what you come up with, and if you would like to explore the code in more detail, I’ll post it on my GitHub account.
In today's data-driven world, efficient data processing plays a pivotal role in the success of any project. Apache Spark, a robust open-source data processing framework, has emerged as a game-changer in this domain. In this article, we will delve into strategies to ensure that your data pipeline is resource-efficient, cost-effective, and time-efficient. This guide is valuable for both data beginners and professionals, serving as a checklist for optimization opportunities. While most of the advice here applies universally to Spark usage, we'll point out specific differences that may affect your application's behavior when using Scala or Python API or writing Spark SQL. Optimizing Data Input Make Use of Data Format In most cases, the data being processed is stored in a columnar format. While this format may not be ideal when you only need to retrieve a few rows from a large partition, it truly excels in analytical use cases. This is particularly beneficial when you have to examine the majority of input rows but are solely interested in a specific subset of columns, which can often number in the hundreds or even thousands within a table. Spark takes full advantage of this storage property by exclusively reading the columns that are involved in subsequent computations. To ensure efficiency, it's crucial to review your execution plan and verify that the earliest project statements are selecting only the columns you will require moving forward. This practice avoids the unnecessary burden of Spark reading hundreds of columns only to discard them later in the process. Don’t Forget About Partitions Now that we've optimized our column selection, let's delve into the efficient retrieval of the necessary rows. As previously mentioned, columnar storage isn't the most efficient choice when you only need to access a few rows out of a massive dataset, and this remains true. However, there are strategies to enhance this situation by cleverly organizing your data. Imagine you're working with sales data collected in hourly intervals from multiple city supermarkets. In your data pipeline, you avoid mixing data from different shops and hours, which is a good practice. Early in the pipeline, you likely perform filtering, but you can take this a step further to prevent Spark from reading superfluous data entirely. By partitioning your data based on both the hour and supermarket_id, Spark can skip irrelevant data with a simple check against the Metastore. However, exercise caution regarding the cardinality of your partitions. If possible, keep the cardinality of your partitioning column in the single or double digits; this makes it an excellent candidate for partitioning. However, if it could potentially reach tens of thousands, consider devising effective aggregation strategies. Returning to the earlier example, envision a supermarket chain like Walmart, where using supermarket_id for partitioning might result in over 10,000 partitions. In such cases, opting for a different partitioning approach, such as using the state, may be more efficient. For instance, in the United States, you can reasonably assume that the cardinality won't exceed 50. To ensure that filter pushdown operates as expected, review your execution plan. In the initial lines where the dataset is loaded, you'll find information like PushedFilters: [*EqualTo(state, CA)]. This confirms that your filtering optimizations are being implemented as intended. Efficient Data Processing Reduce Shuffles Shuffle operations are expensive, so aim to minimize their impact. Reduce the data size before shuffling, apply filtering operations, and consider using "byKey" methods like reduceByKey or aggregateByKey to avoid shuffles whenever possible. You probably won’t be able to get rid of all the shuffles altogether, so consider smart partitioning — it can save resources in future operations. Use Broadcast Continuing our discussion on shuffling, it's essential to consider the option of broadcasting one of your datasets if it's sufficiently small. Broadcasting it to all workers can eliminate the need for a costly shuffle when joining it with your larger "big data" portion. However, it's crucial to navigate the nuances between Spark SQL and the Spark Dataset API in this context. In the Dataset API, using the broadcast method will attempt to broadcast your variable, but it will throw an exception if it doesn't fit in memory. On the other hand, in Spark SQL, the /* BROADCAST(dataset) */ notation functions as a hint. If broadcasting fails to fit in memory, Spark will revert to a regular join. In situations where your supposedly small broadcast dataset unexpectedly grows in size, the outcomes differ between the two approaches. With the Dataset API, you'll notice job failures in Spark, which, while disruptive, clearly highlight the issue. In contrast, in Spark SQL, jobs may become slower, offering greater stability but potentially obscuring the problem for some time. Therefore, understanding these distinctions is crucial when deciding on the broadcasting strategy for your specific use case. Avoid Skews Now, let's delve into the critical aspect of dataset sizes and address the issue of data skews. The most obvious way to identify them is by looking at job processing stats. If you see huge differences between median and max time or input size, or out of 1000 jobs 998 finish in minutes, but 2 leftovers are taking more than an hour — that’s a good indicator of a skew. You can see a skew example below: The longest-running task takes a staggering 7 seconds and reads a massive 116 MB of inputs, whereas the median task processes in just 50 milliseconds and handles a mere 4 KB of data. And here’s an example of a “fixed” pipeline - now the max is just 2 seconds and 10 Mb — still much bigger than a median, but nowhere near the scale it previously was on: Data skews occur when one group being shuffled is disproportionately larger than the others. This can lead to issues such as Out-of-Memory (OOM) errors on a worker node if it cannot accommodate the entire chunk in memory. More commonly, it results in data spillover to disk, causing extended serialization times and excessive time spent in garbage collection (GC). To address data skews, consider techniques like key salting. While we won't delve into the details here, key salting involves introducing a random component to problematic keys and redistributing the data based on the modified keys. This can effectively mitigate skew-related performance bottlenecks. Note: Spark 3.2.0 has Adaptive Query Execution (AQE) enabled by default which should help deal with skewness, but if you see weird task stats - try going with manual salting. Cache Wisely It's important to understand that when you interact with the Spark API, creating new datasets and saving them to variables doesn't actually save any state; instead, you're storing a Directed Acyclic Graph (DAG) of computations required to obtain specific results. Consequently, when you reuse the same variable, Spark will redundantly recompute the same data multiple times. To address this redundancy, it's advisable to cache your dataset when you observe this recomputation pattern. Spark provides various caching options, allowing you to store the dataset either in memory or serialize it to disk. While in-memory caching offers the fastest access, keep in mind that Spark monitors memory consumption and may evict datasets from memory if necessary, as they can be recomputed when needed later. Therefore, it's important to strike a balance and avoid attempting to cache everything all the time, as doing so may not yield the expected performance improvements. Instead, judiciously apply caching to specific datasets that are reused frequently to optimize your Spark application's efficiency. Data Schema and Processing Once More About Formats While it might initially seem enticing to adopt a "flexible" schema, such as storing complex objects as JSON strings, it's essential to consider the long-term implications, especially as your data matures and stabilizes. At this point, it becomes advisable to select the most suitable data format. Opting for native arrays or maps consistently delivers the best performance. This choice offers several advantages, including substantial resource savings by eliminating the need for repetitive deserialization. Additionally, it avoids the overhead of instantiating costly Serialization/Deserialization (SerDe) libraries within User-Defined Functions (UDFs). Furthermore, embracing native arrays or maps can provide added benefits in the future. As Spark continues to evolve and integrate with diverse data formats, you may unlock further optimizations. For instance, this could involve features like the pushdown of reading specific keys within a map, enhancing your application's efficiency and reducing processing overhead. By selecting the optimal data format, you not only improve your current performance but also position yourself for potential performance enhancements in the evolving Spark ecosystem. Avoid UDFs I strongly recommend minimizing the use of UDFs whenever possible, particularly if the same functionality can be achieved using native Spark SQL functions. It's crucial to understand that native Spark functions, while somewhat limited in their capabilities, should be your primary choice, and the utilization of UDFs should be a last resort. There are two key reasons for this recommendation: representation and potential optimizations. Spark manages in-memory data using its proprietary native format. When you call a UDF, each row of data must be transferred to the Java Virtual Machine (JVM) for execution of the function, and afterward, the result is serialized back into Spark's native format. As you can imagine, this process incurs significant computational costs and resource overhead. Moreover, UDFs present a challenge for Spark's optimizers. These optimizers lack visibility into the inner workings of UDFs, rendering them opaque. Consequently, Spark's built-in optimization techniques cannot be applied to UDFs, limiting the potential for performance improvements. By prioritizing native Spark SQL functions and minimizing the reliance on UDFs, you not only reduce computational expenses but also leverage Spark's optimization capabilities to enhance the efficiency of your data processing workflows. Choosing Execution Mode Batch or Streaming? As a final point, I'd like to recommend considering the most suitable execution mode for your needs: batch or streaming. This might initially seem like a significant shift, and indeed, it can be, but the Spark API is designed to abstract away many of the complexities associated with this choice. While Spark is inherently well-tuned for batch datasets (to the extent that even streaming is essentially micro-batching), it's typically the default choice. However, it's worth exploring streaming if your data processing primarily involves small aggregations, where most of the processing can be accommodated within the memory space of just one row. Additionally, if the "side" datasets you need to join with are relatively small, streaming could be a viable option. The decision between batch and streaming should take into account user expectations regarding data output and the significance of data arrival time as a metric. In essence, this choice revolves around aligning your data processing approach with the specific demands and preferences of your users and the importance of real-time data arrival in your application. In this article, I’ve tried briefly summarizing different ways to optimize your Spark application, reducing costs and processing times. While this isn’t an exhaustive list of all possible issues and mitigations, it gives you a good starting point for where to look. The last word of advice before you start your optimization journey would be to not rely on gut feeling, but benchmark your application and look into stats and metrics to know where the actual issues lie.
Step into a world where words and technology unite in a global community effort. Have you ever wondered how your device transforms your voice into text? That's the magic of open-source Large Language Models (LLMs), and you're about to unravel their story. Think of it this way: You are at the heart of this journey. Imagine a team of enthusiastic people worldwide, including developers like you, joining forces. They have a shared mission — making language and technology accessible to everyone. In this article, we're taking you on a tour of open-source LLMs in simple terms. We'll explore how they work, how they've grown, and their pros and cons. It's like peeking behind the curtain to see the inner workings of the tech that shapes how we communicate daily. So, let's dive in and discover how open-source LLMs are changing how we use language in tech. What Is Open-Source LLM? An open-source Large Language Model (LLM) is like a super-smart friend who helps you talk and write better. It's unique because many people worked together to make their brains, and now they share their brainpower with everyone! This LLM can understand what you say and write, and then it can give you excellent suggestions. But the cool part is that you can also tinker with how it works. It's like having a cool toy you can take apart and assemble in your own way. Do you know how you sometimes use computer programs? An open-source LLM is a bit like a program, but it's all about words and sentences. You can use it to make chatbots that talk like humans, help you write emails, or even makeup stories. And because it's open source, lots of intelligent folks can add new things, sort out any hiccups, and make it even better. So, think of this LLM as your word wizard pal. It's not just something you use; it's a team effort. You get to play with it, make it more remarkable, and, together with others, make it the most intelligent word friend around! Having grasped the concept of open-source LLMs, let's take a friendly tour into their world to see how they work their magic. We'll peek behind the curtain and uncover the simple yet incredible mechanisms that let these systems understand and create human-like text. How Do Open-Source LLMs Work? Imagine you and a bunch of folks teaming up to create a super-smart talking machine. Open-source LLMs work precisely like that. You all pitch in data and code; this intelligent machine learns from it. The result? It can chat like a human and power all sorts of cool stuff! Here’s how it exactly works: Step 1: Data Collection and Preprocessing First, you gather massive text data from various sources, including books, articles, websites, and more. This data then gets preprocessed, involving tasks like tokenization, dividing the text into smaller units like words or subwords, and cleaning to remove irrelevant or redundant information. Step 2: Training Corpus Creation Next, you create a training corpus using the preprocessed data. This corpus is what the model will learn from. It's divided into sequences or chunks fed into the model during training. Each sequence consists of tokens, such as words or subwords. Step 3: Model Architecture Selection You choose the architecture of the LLM you're working with. It could be a transformer-based architecture, like GPT (Generative Pre-trained Transformer), which has proven highly effective for language tasks due to its attention mechanisms. Step 4: Model Initialization The selected architecture gets initialized with random weights. You’ll fine-tune these weights during training to make the model adept at understanding and generating human-like text. Step 5: Training Process The actual training begins. The model takes in sequences of tokens and learns to predict the next token in a sequence. It adjusts its internal weights during this process based on the error between its predictions and the actual tokens. You can do this process using optimization algorithms like Adam or SGD (Stochastic Gradient Descent). Step 6: Fine-Tuning After an initial training phase, you fine-tune the model for a specific task. It involves exposing the model to task-specific data and adjusting its weights to perform well. You can fine-tune various language tasks like translation, summarization, question answering, and more. Step 7: Open-Source Release Once you have a well-trained and fine-tuned LLM, you release it as open source. It means sharing the model's architecture, weights, and code with the public. It allows others to use and build upon your work. Step 8: Community Contribution The open-source nature encourages a community of developers, researchers, and enthusiasts to contribute to the model. They suggest improvements, identify issues, or fine-tune the model further for specific tasks. Step 9: Ethical Considerations Throughout the process, ethical considerations are vital. It's essential to avoid biased or harmful outputs from the model. It might involve additional steps like carefully curating the training data, implementing moderation mechanisms, and being responsive to user feedback. Step 10: Continuous Improvement The model is a living entity that you can continuously improve. You can update the training data, fine-tune new tasks, and release newer versions to keep up with the evolving language understanding and generation landscape. Now that you've got the hang of how open-source LLMs work, let's take a friendly stroll through their upsides and downsides. It's like getting to know a new friend — there's a lot to like and some quirks to consider. So, let's chat about these open-source LLMs' excellent and not-so-good aspects. Pros and Cons of Open-Source LLMs Pros of Open-Source LLMs Customization: You can adapt the LLM to specific tasks, enhancing its performance for domain-specific needs. Transparency: The inner workings are visible, fostering trust and enabling users to understand the decision-making process. Innovation: Open-source LLMs encourage collaboration, inviting developers worldwide to contribute and advance the technology. Cost efficiency: Access to the model without licensing fees or restrictions can lower costs for individuals and organizations. Security: Public scrutiny helps identify and address vulnerabilities faster, enhancing overall system security. Cons of Open-Source LLMs Quality variation: Quality control can be uneven due to diverse contributions, leading to inconsistent performance. Misuse risk: Malicious users can exploit open-source LLMs to generate harmful content, misinformation, or deepfakes. Lack of accountability: Challenges arise in attributing model outputs to specific contributors, raising accountability issues. Complexity: Customization demands technical expertise, potentially excluding non-technical users from harnessing the technology. Fragmented development: Divergent adaptations can result in multiple versions, making it harder to maintain a unified standard. Summing Up You've just taken an exciting journey through the open-source LLMs world. It's been quite a ride, hasn't it? From unraveling the power of these models to seeing how they're changing language technology, you've become an expert. Now, you're all set to use models like GPT to do amazing things—writing, problem-solving, or just having fun. Remember, you're not alone in this adventure. The open-source community is like a helpful friend, always there to support you. So, use what you've learned, and let your creativity shine. With open-source LLMs, you've got a whole new world of possibilities at your fingertips. Happy creating!
In today's world, technology is evolving at a rapid pace. One of the advanced developments is edge computing. But what exactly is it? And why is it becoming so important? This article will explore edge computing and why it is considered the new frontier in international data science trends. Understanding Edge Computing Edge computing is a method where data processing happens closer to where it is generated rather than relying on a centralized data-processing warehouse. This means faster response times and less strain on network resources. Key Characteristics of Edge Computing Some of the main characteristics of edge computing include: Speed: Faster data processing and analysis. Efficiency: Less bandwidth usage, which means lower costs. Reliability: More stable, as it doesn't depend much on long-distance data transmission. Benefits of Implementing Edge Computing Implementing edge computing can bring several benefits, such as: Improved performance: It can be analyzed more quickly by processing data locally. Enhanced security: Data is less vulnerable as it doesn't travel long distances. Scalability: It's easier to expand the system as needed. Data Processing at the Edge In data science, edge computing is emerging as a pivotal force, enabling faster data processing directly at the source. This acceleration in data handling allows for realizing real-time insights and analytics previously hampered by latency issues. Consequently, it requires solid knowledge of the field, either earned through experience or through the best data science course, fostering a more dynamic and responsive approach to data analysis, paving the way for innovations and advancements in various fields that rely heavily on data-driven insights. Real-time Analytics and Insights Edge computing revolutionizes business operations by facilitating instantaneous data analysis, allowing companies to glean critical insights in real time. This swift data processing enables businesses to make well-informed decisions promptly, enhancing their agility and responsiveness in a fast-paced market. Consequently, it empowers organizations to stay ahead, giving opportunities to their employees to learn PG in Data Science, optimize their strategies, and seize opportunities more effectively. Enhancing Data Security and Privacy Edge computing enhances data security significantly by processing data closer to its generation point, thereby reducing the distance it needs to traverse. This localized approach diminishes the opportunities for potential security breaches and data interceptions, ensuring a more secure and reliable data handling process. Consequently, it fosters a safer digital ecosystem where sensitive information is better shielded from unauthorized access and cyber threats. Adoption Rates in Various Regions The adoption of edge computing is witnessing a varied pace across different regions globally. Developed nations, with their sophisticated infrastructure and technological advancements, are spearheading this transition, leveraging the benefits of edge computing to foster innovation and efficiency in various sectors. This disparity in adoption rates underscores the pivotal role of robust infrastructure in harnessing the full potential of this burgeoning technology. Successful Implementations of Edge Computing Globally Across the globe, numerous companies are embracing the advantages of edge computing, integrating it into their operational frameworks to enhance efficiency and service delivery. By processing data closer to the source, these firms can offer more responsive and personalized services to their customers, fostering improved customer satisfaction and potentially driving a competitive edge in their respective markets. This successful adoption showcases the tangible benefits and transformative potential of edge computing in the business landscape. Government Policies and Regulations Governments globally are actively fostering the growth of edge computing by formulating supportive policies and regulations. These initiatives are designed to facilitate the seamless integration of this technology into various sectors, promoting innovation and ensuring security and privacy standards are met. Through such efforts, governments are catalyzing a conducive environment for the flourishing of edge computing, steering society toward a more connected and efficient future. Infrastructure Challenges Despite its promising prospects, edge computing has its challenges, particularly concerning infrastructure development. Establishing the requisite infrastructure demands substantial investment in time and resources, posing a significant challenge. The process involves the installation of advanced hardware and the development of compatible software solutions, which can be both costly and time-intensive, potentially slowing the pace of its widespread adoption. Security Concerns While edge computing brings numerous benefits, it raises security concerns, potentially opening up new avenues for cyber vulnerabilities. Data processing at multiple nodes instead of a centralized location might increase the risk of data breaches and unauthorized access. Therefore, robust security protocols will be paramount as edge computing evolves to safeguard sensitive information and maintain user trust. Solutions and Future Directions A collaborative approach between businesses and governments is emerging to navigate the complexities of implementing edge computing. Together, they craft strategies and policies that foster innovation while addressing potential hurdles such as security concerns and infrastructure development. This united front is instrumental in shaping a conducive environment for the seamless integration and growth of edge computing in the coming years. Healthcare Sector In healthcare, edge computing is becoming a cornerstone for advancing patient care. It facilitates real-time monitoring and swift data analysis, providing timely interventions and personalized treatment plans. This enhances the accuracy and efficacy of healthcare services and potentially saves lives by enabling quicker responses in critical situations. Manufacturing Industry In the manufacturing sector, edge computing is vital to streamlining and enhancing production lines. By enabling real-time data analysis directly on the factory floor, it assists in fine-tuning processes, minimizing downtime, and predicting maintenance needs before they become critical issues. Consequently, it fosters a more agile, efficient, and productive manufacturing environment, paving the way for heightened productivity and reduced operational costs. Smart Cities Smart cities, envisioned as the epitome of urban innovation, are increasingly harnessing the power of edge computing to revolutionize their operations. By processing data in affinity to its source, edge computing facilitates real-time responses, enabling cities to manage traffic flows, thereby reducing congestion and commute times. Furthermore, it aids in deploying advanced sensors that monitor and mitigate pollution levels, ensuring cleaner urban environments. Beyond these, edge computing also streamlines public services, from waste management to energy distribution, ensuring they are more efficient, responsive, and tailored to the dynamic needs of urban populations. Integration With IoT and 5G As we venture forward, edge computing is slated to meld seamlessly with burgeoning technologies like the Internet of Things (IoT) and 5G networks. This integration is anticipated to unlock many benefits, including lightning-fast data transmission, enhanced connectivity, and the facilitation of real-time analytics. Consequently, this amalgamation is expected to catalyze a new era of technological innovation, fostering a more interconnected and efficient world. Role in Artificial Intelligence and Machine Learning Edge computing stands poised to be a linchpin in the revolution of artificial intelligence (AI) and machine learning (ML). Facilitating faster data processing and analysis at the source will empower these technologies to function more efficiently and effectively. This synergy promises to accelerate advancements in AI and ML, fostering innovations that could reshape industries and redefine modern convenience. Predictions for the Next Decade In the forthcoming decade, the ubiquity of edge computing is set to redefine our interaction with data fundamentally. This technology, by decentralizing data processing and bringing it closer to the source, promises swifter data analysis and enhanced security and efficiency. As it integrates seamlessly with burgeoning technologies like IoT and 5G, we anticipate a transformative impact on various sectors, including healthcare, manufacturing, and urban development. This shift towards edge computing signifies a monumental leap towards a future where real-time insights and connectivity are not just luxuries but integral components of daily life, facilitating more intelligent living and streamlined operations in numerous facets of society. Conclusion Edge computing is shaping up to be a significant player in the international data science trends. As we have seen, it offers many benefits, including faster data processing, improved security, and the potential to revolutionize industries like healthcare, manufacturing, and urban planning. As we look to the future, the prospects for edge computing seem bright, promising a new frontier in the world of technology. Remember, the world of technology is ever-changing, and staying informed is the key to staying ahead. So, keep exploring data science courses, keep learning, and keep growing!
In our previous post, we delved into problems of pathfinding in graphs, which are inherently connected to solving mazes. When I set out to create a maze map for the Wall-E project, I initially expected to find a quick and easy way to accomplish this task. However, I quickly found myself immersed in the vast and fascinating world of mazes and labyrinths. I was unaware of the breadth and depth of this topic before. I discovered that mazes can be classified in seven different ways, each with numerous variations and countless algorithms for generating them. Surprisingly, I couldn't find any algorithmic books that comprehensively covered this topic, and even the Wikipedia page didn't provide a systematic overview. Fortunately, I stumbled upon a fantastic resource that covers various maze types and algorithms, which I highly recommend exploring. I embarked on a journey to learn about the different classifications of mazes, including dimensional and hyperdimensional variations, perfect mazes versus unicursal labyrinths, planar and sparse mazes, and more. How To Create a Maze My primary goal was to generate a 2D map representing a maze. While it would have been enticing to implement various maze-generation algorithms to compare them, I also wanted a more efficient approach. The quickest solution I found involved randomly selecting connected cells. That's precisely what I did with mazerandom. This one-file application creates a grid table of 20 x 20 cells and then randomly connects them using a Depth-First Search (DFS) traversal. In other words, we're simply carving passages in the grid. If you were to do this manually on paper, it would look something like this: To achieve this algorithmically, we apply Depth-First Search to the grid of cells. Let's take a look at how it's done in the Main.cpp. As usual, we represent the grid of cells as an array of arrays, and we use a stack for DFS: C++ vector<vector<int>> maze_cells; // A grid 20x20 stack<Coord> my_stack; // Stack to traverse the grid by DFS my_stack.push(Coord(0, 0)); // Starting from very first cell We visit every cell in the grid and push its neighbors onto the stack for deep traversal: C++ ... while (visitedCells < HORIZONTAL_CELLS * VERTICAL_CELLS) { vector<int> neighbours; // Step 1: Create an array of neighbour cells that were not yet visited (from North, East, South and West). // North is not visited yet? if ((maze_cells[offset_x(0)][offset_y(-1)] & CELL_VISITED) == 0) { neighbours.push_back(0); } // East is not visited yet? if ((maze_cells[offset_x(1)][offset_y(0)] & CELL_VISITED) == 0) { neighbours.push_back(1); } ... // Do the same for West and South... The most complex logic involves marking the node as reachable (i.e., no wall in between) with CELL_PATH_S, CELL_PATH_N, CELL_PATH_W, or CELL_PATH_E: C++ ... // If we have at least one unvisited neighbour if (!neighbours.empty()) { // Choose random neighbor to make it available int next_cell_dir = neighbours[rand() % neighbours.size()]; // Create a path between the neighbour and the current cell switch (next_cell_dir) { case 0: // North // Mark it as visited. Mark connection between North and South in BOTH directions. maze_cells[offset_x(0)][offset_y(-1)] |= CELL_VISITED | CELL_PATH_S; maze_cells[offset_x(0)][offset_y(0)] |= CELL_PATH_N; // my_stack.push(Coord(offset_x(0), offset_y(-1))); break; case 1: // East // Mark it as visited. Mark connection between East and West in BOTH directions. maze_cells[offset_x(1)][offset_y(0)] |= CELL_VISITED | CELL_PATH_W; maze_cells[offset_x(0)][offset_y(0)] |= CELL_PATH_E; my_stack.push(Coord(offset_x(1), offset_y(0))); break; ... // Do the same for West and South... } visitedCells++; } else { my_stack.pop(); } ... Finally, it calls the drawMaze method to draw the maze on the screen using the SFML library. It draws a wall between two cells if the current cell isn't marked with CELL_PATH_S, CELL_PATH_N, CELL_PATH_W, or CELL_PATH_E. However, this maze doesn't guarantee a solution. In many cases, it will generate a map with no clear path between two points. While this randomness might be interesting, I wanted something more structured. The only way to ensure a solution for the maze is to use a predetermined structure that connects every part of the maze in some way. Creating a Maze Using Graph Theory Well-known maze generation algorithms rely on graphs. Each cell is a node in the graph, and every node must have at least one connection to other nodes. As mentioned earlier, mazes come in many forms. Some, called "unicursal" mazes, act as labyrinths with only one entrance, which also serves as the exit. Others may have multiple solutions. However, the process of generation often starts with creating a "perfect" maze. A "perfect" maze, also known as a simply-connected maze, lacks loops, closed circuits, and inaccessible areas. From any point within it, there is precisely one path to any other point. The maze has a single, solvable solution. If we use a graph as the internal representation of our maze, constructing a spanning tree ensures that there is a path from the start to the end. In computer science terms, such a maze can be described as a spanning tree over the set of cells or vertices. Multiple spanning trees may exist, but the goal is to ensure at least one solution from the start to the end, as shown in the example below: The image above depicts only one solution, but there are actually multiple paths. No cell is isolated and impossible to reach. So, how do we achieve this? I discovered a well-designed mazegenerator codebase by @razimantv that accomplishes this, generating mazes in SVG file format. Therefore, I forked the repository and based my solution on it. Kudos to @razimantv for the elegant OOP design, which allowed me to customize the results to create visually appealing images using the SFML library or generate a text file with the necessary map description for my Wall-E project. I refactored the code to remove unnecessary components and focus exclusively on rectangular mazes. However, I retained support for various algorithms to build a spanning tree. I also added comments throughout the codebase for easier comprehension, so I don't need to explain it in every detail here. The main pipeline can be found in \mazegenerator\maze\mazebaze.cpp: C++ /** * \param algorithm Algorithm that is used to generate maze spanning tree. */ void MazeBase::GenerateMaze(SpanningtreeAlgorithmBase* algorithm) { // Generates entire maze spanning tree auto spanningTreeEdges = algorithm->SpanningTree(_verticesNumber, _edgesList); // Find a solution of a maze based on Graph DFS. _Solve(spanningTreeEdges); // Build a maze by removing unnecessary edges. _RemoveBorders(spanningTreeEdges); } I introduced visualization using the SFML graphics library, thanks to a straightforward _Draw_ function.While DFS is the default algorithm for creating a spanning tree, there are multiple algorithms available as options.The result is a handy utility that generates rectangular "perfect" mazes and displays them on the screen: As you can see, it contains exactly one input and one output at the left top and right bottom corners. The code still generates SVG file, which is a nice addition (though, it is the core function of the original codebase). Now, I can proceed with my experiments in the Wall-E project, and I leave you here, hoping that you're inspired to explore this fascinating world of mazes and embark on your own journey.Stay tuned!
Generative AI refers to a category of artificial intelligence techniques that involve generating new data, such as images, text, audio, and more, based on patterns learned from existing data. Generative models like Generative Adversarial Networks (GANs) and Variational Auto-Encoders (VAEs) have demonstrated remarkable capabilities in generating realistic and diverse data for various purposes, including data collection. Leverage Generative AI for Data Collection Data Augmentation Generative models can create new samples that closely resemble your existing data. By incorporating these generated samples into your training data, you can improve your model's performance and resilience, particularly in tasks such as image classification and object detection. Imputation of Missing Data If your datasets have missing values, generative models can fill those gaps with plausible values. This can enhance the quality and comprehensiveness of your data. Synthetic Data Generation Obtaining a diverse dataset might be challenging due to privacy concerns or data scarcity. Generative models can be trained on a small dataset to generate synthetic data that mirrors the actual data distribution. Merging this synthetic data with your real data can effectively expand your dataset. Data Generation for Testing and Validation In situations where you require representative data to test and validate your models or algorithms, generative models can produce synthetic data covering a wide range of scenarios. This aids in ensuring the robustness of your solution. Creative Content Generation Generative models can craft artistic and creative content, including artwork, music, and literature. This is valuable for applications like content creation, where a variety of creative outputs is desired. Data Preprocessing and Transformation Generative models can convert data from one domain to another. For instance, in style transfer, a generative model can change images from one artistic style to another. Anomaly Detection Generative models can learn the typical data distribution and then identify anomalies or outliers that deviate from that distribution. This can be beneficial for detecting fraudulent transactions or abnormal behavior. It's crucial to recognize that while generative AI offers numerous benefits for data collection and enhancement, careful evaluation is necessary when applying these techniques. The quality and suitability of the generated data should be thoroughly assessed before integration into your workflows or models. Additionally, ethical considerations, privacy concerns, and legal implications should be considered, especially when generating synthetic data. Mastering Seamless and Intelligent Data Transfer With Generative AI Achieving seamless and intelligent data transfer using Generative AI entails several steps and considerations. Here's a general outline of the process: Data Preprocessing Prepare your source data by cleaning, preprocessing, and structuring it to ensure it's suitable for input to the Generative AI model. Generative AI Model Selection Depending on your specific data and use case, choose an appropriate generative model like Generative Adversarial Networks (GANs) or Variational auto-encoders (VAEs). Model Training Train the selected generative model using your preprocessed data. During training, the model learns the underlying data patterns and distributions. Data Generation Once the generative model is trained, use it to generate new data samples resembling the original data distribution. This generated data can be in various formats, such as images, text, or other types of data. Data Transformation (Optional) If you need to transfer data across different domains or styles, apply transformations using the generative model. For instance, style transfer techniques can transform images from one artistic style to another. Data Integration Combine the generated data with your existing dataset or target application. This might involve merging synthetic data with real data to create a more extensive and diverse dataset. Testing and Validation Thoroughly assess the quality and relevance of the generated data. Ensure it aligns with your requirements and objectives. Data Transfer and Deployment Integrate the generated data into your desired workflows, applications, or systems where intelligent data transfer is essential. Monitoring and Iteration Continuously monitor the generative AI model's performance and the impact of transferred data. Iterate and refine the process as needed to achieve optimal results. Fostering Personalized Creativity Through Generative AI Harnessing the power of generative models to create unique and tailored experiences involves consuming data for creativity and personalization through Generative AI. Here's a guide to achieving this: Understanding generative AI: Familiarize yourself with generative AI techniques, including Generative Adversarial Networks (GANs), Variational auto-encoders (VAEs), and other generative models. Understand their capabilities and potential applications. Data collection and preparation: Gather diverse and representative datasets aligned with your creative goals. These datasets may encompass images, text, audio, or other relevant data types. Model selection: Choose a suitable generative model based on your objectives. For example, GANs can be effective for image generation, while language models like GPT-3 could be beneficial for text-related tasks. Training the generative model: Train the chosen generative model using your prepared data. This involves adjusting model parameters, architecture, and hyperparameters to achieve the desired output quality. Creative content generation: Utilize the trained generative model to produce creative content, such as visual artworks, music compositions, written pieces, and more. Personalization: Incorporate user preferences and inputs to customize the generated content. This can involve themes, genres, moods, or prompts provided by users. Feedback loop: Establish a feedback mechanism to refine the generative model based on user preferences and evaluations. This iterative process enhances content quality and personalization. Ethical considerations: Ensure that the generated content adheres to ethical guidelines, avoiding biases, offensive material, or sensitive information. User experience (UX) design: Design intuitive interfaces or platforms for users to interact with and customize the generative AI. User experience plays a pivotal role in enhancing engagement. Testing and validation: Rigorously test and validate the generated content to ensure its quality, relevance, and appeal to users. Cultivating Creative Brilliance Fostering a creative, data-driven culture using Generative AI requires a strategic approach to integrating data-driven decision-making and generative AI technologies into your organization's creative processes. Here's a step-by-step guide to achieving this: Educate and build awareness: Introduce Generative AI and its potential benefits to your creative teams. Provide training sessions and workshops to help them understand its applications. Align with goals and vision: Clearly articulate how integrating Generative AI aligns with your organization's creative goals and long-term vision. Leadership support: Obtain leadership support by demonstrating how Generative AI can drive creative excellence and contribute to success. Data strategy: Develop a comprehensive data strategy outlining the data needed for creative projects, data collection, preprocessing, and the application of Generative AI. Cross-functional collaboration: Facilitate collaboration between creative teams, data scientists, and technology experts. Identify use cases: Identify use cases where Generative AI can enhance creativity, like content generation and design exploration. Data integration: Incorporate Generative AI into creative workflows, integrating generated content with the work of designers, artists, and writers. Prototype and experiment: Encourage teams to experiment with Generative AI in small-scale projects to showcase its potential impact. Feedback and iteration: Establish feedback loops to gather insights from creative teams using Generative AI. Ethical considerations: Address ethical considerations, such as biases, transparency, and privacy. Skill development: Provide training for creative professionals to enhance their understanding of Generative AI. Showcase success stories: Highlight successful projects where Generative AI enhanced creativity and drove innovation. Iterative implementation: Gradually expand Generative AI integration into various creative projects, learning and refining the approach. Measure impact: Develop metrics to measure Generative AI's impact on creativity, innovation, and user engagement. Continuous learning: Stay updated on Generative AI advancements and adapt strategies as technology evolves. Guiding Ethical and Responsible Data Practices in Generative AI Ethical and responsible generative AI data practices involve principles and guidelines that ensure the ethical use of data when employing generative AI techniques. These practices uphold rights, privacy, and well-being, prevent biases, and promote transparency and accountability. Here are key ethical and responsible generative AI data practices: Informed data collection and use: Collect data with consent and transparency, using it only for intended and lawful purposes. Privacy protection: Anonymize or de-identify personal data and implement robust data security measures. Bias detection and mitigation: Identify and minimize biases in training data to prevent unfair or discriminatory outcomes. Transparency and explainability: Make the generative AI process understandable and communicate limitations and potential risks. User empowerment and control: Give users control over generated content and allow feedback. Data minimization: Collect only the necessary data for generative AI applications. Accountability and governance: Establish accountability and implement policies for the ethical use of generative AI. Validation and testing: Rigorously test and validate generated content before deployment. Continuous monitoring and auditing: Monitor generative AI behavior and conduct regular audits. Community engagement: Engage with stakeholders and experts to gather feedback on ethical implications. Legal compliance: Ensure compliance with data protection laws and industry standards. Education and training: Educate employees and stakeholders about ethical considerations. By adhering to these practices, organizations can leverage generative AI while upholding ethical standards. Forging Frontiers of Innovation Pioneering innovation with Generative AI involves using generative models to create imaginative solutions. Here's a roadmap for this journey: Education and exploration: Understand Generative AI concepts and explore existing applications and case studies. Identify opportunities: Find areas in your domain that can benefit from Generative AI. Cross-disciplinary collaboration: Foster collaboration between experts in AI, data science, design, and other fields. Concept generation: Brainstorm and sketch out innovative projects using Generative AI. Prototype development: Build prototypes to test concepts. Data collection and preprocessing: Gather and preprocess relevant datasets. Model development and training: Develop and train Generative AI models. Iterative refinement: Continuously refine models based on feedback. Validation and testing: Test and validate generated content. Implementation and deployment: Integrate Generative AI Solutions Showcase and demonstration: Highlight outcomes of Generative AI projects. Continuous learning and adaptation: Stay updated and adapt strategies based on emerging trends. Ethical considerations: Address biases, transparency, and privacy. Collaborate with the community: Engage with Generative AI Communities By following this roadmap, you can drive innovation with Generative AI and create transformative solutions. Conclusion Generative AI involves creating diverse data using patterns from existing information, with models like GANs and VAEs proving adept in tasks such as data augmentation, missing data imputation, and creative content generation. Adherence to ethical guidelines and careful evaluation are imperative. Effective utilization necessitates preprocessing, model selection, training, integration, and validation for seamless data transfer. Tailoring personalized experiences requires model training, creative content generation, personalization, and ethical considerations. Cultivating a creative culture involves education, alignment, collaboration, and ethical awareness. Ethical data practices involve transparency, bias detection, privacy protection, and accountability. Innovating with Generative AI entails exploration, cross-disciplinary collaboration, prototype development, validation, and continuous learning. Balancing innovation and ethics is crucial for leveraging Generative AI's potential.
In this sixth article of the series, we describe and provide the full source for a mixed reality app that takes any visual and audio input from a user's surroundings, processes it with various AI, and returns output of summaries, results of generative AI, etc. This is the sixth piece in a series on developing XR applications and experiences using Oracle and focuses on visual and audio input from a user's surroundings, processing it with various AI, and returning output of summaries, results of generative AI, etc. Find the links to the first five articles below: Develop XR With Oracle, Ep 1: Spatial, AI/ML, Kubernetes, and OpenTelemetry Develop XR With Oracle, Ep 2: Property Graphs and Data Visualization Develop XR With Oracle, Ep 3: Computer Vision AI, and ML Develop XR With Oracle, Ep 4: Digital Twins and Observability Develop XR With Oracle, Ep 5: Healthcare, Vision AI, Training/Collaboration, and Messaging As with the previous posts, I will specifically show applications developed with Oracle database and cloud technologies using Magic Leap 2, HoloLens 2, Oculus, iPhone and Android, and PC and written using the Unity platform and OpenXR (for multi-platform support), Apple Swift, and WebXR. Throughout the blog, I will reference the corresponding demo video below: Extended Reality (XR) and AI in Everyday Life With Contextual and Situational Awareness I will refer the reader to the first article in this series (again, the link is above) for an overview of XR. This piece is focused on Mixed Reality/Augmented Reality use cases and AI, though there are certainly an amazing number of examples where AI is used in VR and we will explore those in future blogs in the series. The combination used to develop these applications is a powerful and perfect one. Unity, Cohere, and other Oracle AI services, and at the heart of the solution the Oracle database. A Perfect XR AI Fullstack Solution: Unity, Kubernetes, Oracle AI and Cohere, and Oracle Database The application architecture consists of a full stack with Unity creating the front-end, Java Spring Boot, and other microservices running in Kubernetes (which can consist of NVidia compute) forming the backend and calling out to the various AI services and the Oracle database storing the various information including vector, spatial, etc. data. Examples Here are some of the many examples. Each is triggered by a voice command via the XR headset's voice recognition system. "Explain This..." In reaction to this command, the Unity client-side app takes a picture from the headset wearer's point of view and sends the picture to a serverside Spring Boot app running in Kubernetes (though Kubernetes is not a requirement nor is Spring Boot, and this can be achieved with Python, Javascript, .NET, and other languages including languages running directly within the database). The server-side app calls the Oracle Vision AI service, which detects and returns the text in the picture. The text can be at any angle, etc., and the service will interpret it correctly. The server-side app then takes this text and passes it to Cohere (or Hugging Face or OpenAI) to get an explanation of the health report in both text and speech, in simple terms, and suggestions on ways to improve results/health. The image, content, and summary are stored in the database where further analysis can be conducted, from basic advanced text search to image analysis, Oracle Machine Learning AI, etc. This use case shows how complex medical information and health test results can be easily and quickly interpreted and corrective actions taken by a common person without the need for or supplementary to a professional health care worker. "Summarize This..." This example is very similar to the "Explain this" example and simply illustrates the versatility of such command functionality. In this case, the content is summarized, again in both text and speech, in x (e.g., 3) sentences or less. This use case shows how mass amounts of information can be quickly consumed. “Select All From Summaries...” In reaction to this command, the Unity client-side app calls the server side to query the Oracle database and return various information such as the images and texts of the previous commands that were recorded. This use case obviously goes beyond this scenario. It is effectively the ability to query the database for anything and do so from anywhere and use all of the complex features the Oracle database has to offer. Queries can be based on text, speech, images, AI of voice-to-text-to-SQL, situational and environmental information and sensors, etc., and include advanced analytic queries, etc. "Transcribe [YouTube Video]..." As opposed to "Transcribe Audio," which takes or records an audio clip for transcription, in reaction to this command, the app will check to see if a YouTube URL is in the user's view, and if so, will use the API to get the transcription of the video. It can additionally be "transcribed and summarized" as described previously. This use case again shows how mass amounts of information can be quickly consumed and can be taken from a number of different input sources including video and audio which may be advantageous for a number of reasons or for those with vision or hearing impairment. “Generate Image [Of ...] Stop Generate Image” In reaction to this command, the Unity app starts recording the user's speech and stops when the user says "Stop generating image." The speech is sent to the server-side application which then transcribes it, removes "stop generate image" from the end of the transcription, and sends the text description to Stable Diffusion (or DALL-E, etc.) which creates an image and passes it (or it's URL location) back to the application and headset which displays the image in front of the user. This is a very simple example of course, and this functionality is no longer limited to 2D but also 3D images, sounds, etc. It demonstrates the ability to dynamically generate and add visual context for quick storyboarding, collaboration, and training, AEC (architecture, engineering, and construction), etc., and, of course, gaming. This can also be used with USD (Universal Scene Description) and tech such as NVidia's Omniverse platform for extremely compelling collaboration experiences. “Tell a Dystopian Story About This and Give Sentiments...” In reaction to this command, again the Unity client-side app takes a picture from the headset wearer's point of view and sends it to the server-side component that this time, uses Oracle Vision AI to identify all of the objects in the user's view. It then sends these objects to Cohere (or other AI) and asks that a story of a certain style be generated from the contents. This story is then further analyzed using Oracle's AI Sentiment Analysis service and the story and the sentiment analysis are sent back to the user to view in both text and speech. This use case again shows not only a potential for creativity and creating of a story around a mood or interesting setting of objects but can be used for situational analysis in any number of military and police, health and safety, social, etc., scenarios. In the third blog of this series (linked in the opening of this article), two other examples were given. “Identify Objects...” In reaction to this command, again the Unity client-side app takes a picture from the headset wearer's point of view and sends it to the server-side component that this time uses Oracle Vision AI/Object Detection to detect the objects and their relative coordinates. These are sent back to the Unity client-side app which projects raycasts through these coordinates to draw bounding boxes with identification labels on the spatial location of the objects in the room and to also speech the object names from the spatial coordinates where they are located. As far as use cases in this and other commands/functionality mentioned, it is not difficult to imagine the potential to assist with vision impairment, Alzheimer’s, identification of unknown and difficult-to-isolate items, analysis of threats, interests, etc., by having the XR device give contextual audio and visual feedback about one's surroundings. "Start Conversation..." In reaction to this command, again the Unity client-side app takes a picture from the headset wearer's point of view and sends it to the server-side component that this time uses Oracle Vision AI/Document AI to retrieve the text found (various book titles), pick a title at random, and send the text to a number of (at that point GPT-3 was the latest) conversation models which then feedback various conversational responses. These responses, or again any information from various models, are given to the user. There are again so many situational awareness use cases that such functionality provides but the ability to strike up a good conversation is powerful enough. The Source Code, OpenXR, and Other Dev Details I will describe key snippets of the programs and components involved in this application in this blog. The full source code for both the Unity frontend and Java backend can be found on GitHub. This repo will continue to grow with examples of other functionality, different languages, frameworks, etc. It is also where code for an upcoming "Develop XR with Oracle" workshop will be located. A basic understanding of Unity and Java (for these particular examples) will be required along with particulars of the XR headset you are using. This application has been tested on Hololens 2 (shown in the pictures and video of this blog) and Magic Leap 2. The Unity application is coded using MRTK 3 (mixed reality toolkit) which conforms to the OpenXR standard. Magic Leap recently joined the MRTK steering committee which was formed by Microsoft and includes Qualcomm as a member. This wide adoption of OpenXR makes applications written to it more portable; however, Apple is not a member, and similar to other technologies where software and varying hardware must work together, even with this standard, code must have adapters for certain native functionality, particularly in the XR space where approaches and features may differ greatly between products. For example, the application(s) described are actually fairly simple (where 1/input generally has a device-specific setup, whereas 2, 3, and to a large extent 4, are generally portable as-is): Input (picture, video, audio, etc.) is taken from the XR device. Input is sent to the server (for AI, database, etc., processing). The response is received from the server side. The content of the response is given as output (text, picture, video, sound, etc.). Let's look at the "no code" and code involved in the order list above. We add an MRTK object to our Unity scene. This object contains profiles with configuration for Experience Settings, Camera, Input, Boundary, Teleport, Spatial Awareness, etc. Under Input, there are various settings for Controllers, Gestures, etc. including Speech. Here, we simply specify Keywords such as "Explain this," "Generate image," etc. We then add a Microsoft.MixedReality.Toolkit.Input.SpeechInputHandler component to the scene which maps the keywords we defined to actions. For example, here we see the ExplainThis method of an object with the TakePicAndProcessAI script/class will be called when the user says "Explain this." Looking closer at the TakePicAndProcessAI C# source, we see the following for ExplainThis (similar to other commands involving the general process of sending a picture for AI processing: C# public void ExplainThis() { endPoint = "visionai/explain"; TakePicAndProcess(); } TakePicAndProcess() contains logic and settings to take a picture and (temporarily) save it locally as well as an OnCapturedPhotoToDisk callback. OnCapturedPhotoToDisk in turn loads the pic/image into a texture for display in front of the user and calls the ProcessAI subroutine. This ProcessAI subroutine has code that is dynamic based on parameters provided to, it but has the overall purpose of making network calls to the serverside and marshaling data to and from it. It also displays the returned AI content in a text field (or 2D or 3D object, as the case may be) for the user to see, executes text-to-speech for the user to hear, etc. C# byte[] imageData = image.EncodeToPNG(); WWWForm form = new WWWForm(); form.AddBinaryData("file", imageData, "image.png", "image/png"); if (genopts != null) { form.AddField("genopts", genopts); genopts = null; } Debug.Log("Making AI etc. calls, providing file: " + filePath + "..."); UnityWebRequest request = UnityWebRequest.Post(backendURL + "/" + endPoint, form); yield return request.SendWebRequest(); if (request.result == UnityWebRequest.Result.Success) { string jsonResponse = request.downloadHandler.text; if (textMesh != null) textMesh.text = jsonResponse; textToSpeechLogic.talk(textToSpeechObject.GetComponent<TextToSpeech>(), jsonResponse); Debug.Log(jsonResponse); } On the server side, we have simple-to-use logic such as the following to process the image sent from the Unity app Vision AI and extract the text found: Java features.add(detectImageFeature); features.add(textDetectImageFeature); InlineImageDetails inlineImageDetails = InlineImageDetails.builder().data(bytesOfImagePassedInFromUnityApp).build(); AnalyzeImageRequest request = AnalyzeImageRequest.builder().analyzeImageDetails(analyzeImageDetails).build(); AnalyzeImageResponse response = aiServiceVisionClient.analyzeImage(request); And the following to process the text retrieved from Vision AI to get a summary using Cohere (or Hugging Face or OpenAI): Java AsyncHttpClient client = new DefaultAsyncHttpClient(); client.prepare("POST", "https://api.cohere.ai/v1/summarize") .setHeader("accept", "application/json") .setHeader("content-type", "application/json") .setHeader("authorization", "[your bearer token here]") .setBody("{\"length\":\"medium\",\"format\":\"paragraph\",\"model\":\"summarize-xlarge\",\"extractiveness\":\"low\",\"temperature\":0.3," + "\"text\":\"" + textRetrievedFromVisionAI + "\"}").execute(); As well as the following to process Oracle database storage, retrieval, and other logic. Java //Using JPA summaryRepository.saveAndFlush(new Summary(explanationOfResults, bytes)); Again, this server-side logic can be in any language as all OCI services, Cohere services, and the Oracle Database support them all. Additional Thoughts I have given some ideas and examples of how AI and XR can be used together and facilitated by Oracle. I look forward to putting out more blogs on this topic and other areas of XR with Oracle Cloud and Database soon including the use of new advanced features in the Spatial component of the Oracle Database for geometric storage (.OBJ mesh, point cloud, etc.), analysis, and processing that works with Unity at runtime in real-time and the ability to run server-side languages colocated within the Oracle database itself. A "Develop XR with Oracle" workshop will also be released in the near future. Please see my other publications for more information on XR and Oracle cloud and database, as well as various topics around modern app dev including microservices, observability, transaction processing, etc. Finally, please feel free to contact me with any questions or suggestions for new blogs and videos, as I am very open to suggestions. Thanks for reading and watching.
Code scanning for vulnerability detection for exposure of security-sensitive parameters is a crucial practice in MuleSoft API development. Code scanning involves the systematic analysis of MuleSoft source code to identify vulnerabilities. These vulnerabilities could range from hardcoded secure parameters like password or accessKey to the exposure of password or accessKey in plain text format in property files. These vulnerabilities might be exploited by malicious actors to compromise the confidentiality, integrity, or availability of the applications. Lack of Vulnerability Auto-Detection MuleSoft Anypoint Studio or Anypoint platform does not provide a feature to keep governance on above mentioned vulnerabilities. It can be managed by design time governance, where a manual review of the code will be needed. However, there are many tools available that can be used to scan the deployed code or code repository to find out such vulnerabilities. Even you can write some custom code/script in any language to perform the same task. Writing custom code adds another complexity and manageability layer. Using Generative AI To Review the Code for Detecting Vulnerabilities In this article, I am going to present how Generative AI can be leveraged to detect such vulnerabilities. I have used the Open AI foundation model “gpt-3.5-turbo” to demonstrate the code scan feature to find the aforementioned vulnerabilities. However, we can use any foundation model to implement this use case. This can be implemented using Python code or any other code in another language. This Python code can be used in the following ways: Python code can be executed manually to scan the code repository. It can be integrated into the CICD build pipeline, which can scan and report the vulnerabilities and result in build failure if vulnerabilities are present. It can be integrated into any other program, such as the Lambda function, which can run periodically and execute the Python code to scan the code repository and report vulnerabilities. High-Level Architecture Architecture There are many ways to execute the Python code. A more appropriate and practical way is to integrate the Python code into the CICD build pipeline. CICD build pipeline executes the Python code. Python code reads the MuleSoft code XML files and property files. Python code sends the MuleSoft code content and prompts the OpenAI gpt-3.5-turbo model. OpenAI mode returns the hardcoded and unencrypted value. Python code generates the report of vulnerabilities found. Implementation Details MuleSoft API project structure contains two major sections where security-sensitive parameters can be exposed as plain text. src/main/mule folder contains all the XML files, which contain process flow, connection details, and exception handling. MuleSoft API project may have custom Java code also. However, in this article, I have not considered the custom Java code used in the MuleSoft API. src/main/resources folder contains environment property files. These files can be .properties or .yaml files for development, quality, and production. These files contain property key values, for example, user, password, host, port, accessKey, and secretAccesskey in an encrypted format. Based on the MuleSoft project structure, implementation can be achieved in two steps: MuleSoft XML File Scan Actual code is defined as process flow in MuleSoft Anypoint Studio. We can write Python code to use the Open AI foundation model and write a prompt that can scan the MuleSoft XML files containing the code implementation to find hardcoded parameter values. For example: Global.xml/Config.xml file: This file contains all the connector configurations. This is standard recommended by MuleSoft. However, it may vary depending on the standards and guidelines defined in your organization. A generative AI foundation model can use this content to find out hardcoded values. Other XML files: These files may contain some custom code or process flow calling other for API calls, DB calls, or any other system call. This may have connection credentials hard-coded by mistake. A generative AI foundation model can use this content to find out hardcoded values. I have provided the screenshot of a sample MuleSoft API code. This code has three XML files; one is api.xml, which contains the Rest API flow. Process.xml has a JMS-based asynchronous flow. Global.xml has all the connection configurations. api.xml process.xml global.xml For demonstration purposes, I have used a global.xml file. The code snippet has many hardcoded values for demonstration. Hardcoded values are highlighted in red boxes: Python Code The Python code below uses the Open AI foundation model to scan the above XML files to find out the hard-coded values. Python import openai,os,glob from dotenv import load_dotenv load_dotenv() APIKEY=os.getenv('API_KEY') openai.api_key= APIKEY file_path = "C:/Work/MuleWorkspace/test-api/src/main/mule/global.xml" try: with open(file_path, 'r') as file: file_content = file.read() print(file_content) except FileNotFoundError: except Exception as e: print("An error occurred:", e) message = [ {"role": "system", "content": "You will be provided with xml as input, and your task is to list the non-hard-coded value and hard-coded value separately. Example: For instance, if you were to find the hardcoded values, the hard-coded value look like this: name=""value"". if you were to find the non-hardcoded values, the non-hardcoded value look like this: host=""${host}"" "}, {"role": "user", "content": f"input: {file_content}"} ] response = openai.ChatCompletion.create( model="gpt-3.5-turbo", messages=message, temperature=0, max_tokens=256 ) result=response["choices"][0]["message"]["content"] print(result) Once this code is executed, we get the following outcome: The result from the Generative AI Model Similarly, we can provide api.xml and process.xml to scan the hard-coded values. You can even modify the Python code to read all the XML files iteratively and get the result in sequence for all the files. Scanning the Property Files We can use the Python code to send another prompt to the AI model, which can find the plain text passwords kept in property files. In the following screenshot dev-secure.yaml file has client_secret as the encrypted value, and db.password and jms.password is kept as plain text. config file Python Code The Python code below uses the Open AI foundation model to scan config files to find out the hard-coded values. Python import openai,os,glob from dotenv import load_dotenv load_dotenv() APIKEY=os.getenv('API_KEY') openai.api_key= APIKEY file_path = "C:/Work/MuleWorkspace/test-api/src/main/resources/config/secure/dev-secure.yaml" try: with open(file_path, 'r') as file: file_content = file.read() except FileNotFoundError: print("File not found.") except Exception as e: print("An error occurred:", e) message = [ {"role": "system", "content": "You will be provided with xml as input, and your task is to list the encrypted value and unencrypted value separately. Example: For instance, if you were to find the encrypted values, the encrypted value look like this: ""![asdasdfadsf]"". if you were to find the unencrypted values, the unencrypted value look like this: ""sdhfsd"" "}, {"role": "user", "content": f"input: {file_content}"} ] response = openai.ChatCompletion.create( model="gpt-3.5-turbo", messages=message, temperature=0, max_tokens=256 ) result=response["choices"][0]["message"]["content"] print(result) Once this code is executed, we get the following outcome: result from Generative AI Impact of Generative AI on the Development Life Cycle We see a significant impact on the development lifecycle. We can think of leveraging Generative AI for different use cases related to the development life cycle. Efficient and Comprehensive Analysis Generative AI models like GPT-3.5 have the ability to comprehend and generate human-like text. When applied to code review, they can analyze code snippets, provide suggestions for improvements, and even identify patterns that might lead to bugs or vulnerabilities. This technology enables a comprehensive examination of code in a relatively short span of time. Automated Issue Identification Generative AI can assist in detecting potential issues such as syntax errors, logical flaws, and security vulnerabilities. By automating these aspects of code review, developers can allocate more time to higher-level design decisions and creative problem-solving. Adherence To Best Practices Through analysis of coding patterns and context, Generative AI can offer insights on adhering to coding standards and best practices. Learning and Improvement Generative AI models can "learn" from vast amounts of code examples and industry practices. This knowledge allows them to provide developers with contextually relevant recommendations. As a result, both the developers and the AI system benefit from a continuous learning cycle, refining their understanding of coding conventions and emerging trends. Conclusion In conclusion, conducting a code review to find security-sensitive parameters exposed as plain text using OpenAI's technology has proven to be a valuable and efficient process. Leveraging OpenAI for code review not only accelerated the review process but also contributed to producing more robust and maintainable code. However, it's important to note that while AI can greatly assist in the review process, human oversight and expertise remain crucial for making informed decisions and fully understanding the context of the code.
TreeMap is a Java collection that structures the data in the form of an ordered key and their respective values. It has been available since JDK 1.2. Internally, TreeMap uses a red-black tree to structure the data, which is a self-balancing binary tree. The keys in TreeMap are unique identifiers, and by default, TreeMap arranges the data in a natural ordering of keys. For the integer keys, it is stored in the ascending order of the keys, and for the String key, the data will be stored in the alphabetic order. We can always override the default ordering of data and can inject custom sorting by using a comparator during the TreeMap creation to sort in any defined manner as per the logic provided in the comparator. We will discuss in detail a few of the custom hybrid sorting approaches along with some code examples in this article. One of the most popular searching and sorting data structures is the binary search tree (BST). When it comes to search operation performance, a binary search tree has a worst-case complexity of O(n), which is almost like a linear search. Red-black trees have a consistent time complexity of O(log n) as it self-balances itself for every insertion and deletion operation and ensures that the tree is always balanced. This means that the tree adjusts itself automatically in an optimal manner, which ensures the search and find operation is very efficient and never exceeds the O(log n) time complexity for any dataset as well as any kind of search operation. It uses a simple but powerful mechanism to maintain a balanced structure by coloring each node in the tree either red or black. It can be called a self-balancing binary search tree. It has good, efficient, worst-case running time complexity. Why Use TreeMap? Most of the BST operations (like search, delete, search, and update) take O(log n) time, where n is the number of nodes in the binary search tree. The cost of these operations may become O(n) for a skewed binary tree where all the key is going in one specific path, i.e., it's either a left-skewed binary tree where all elements go on the left path only or a right-skewed binary search tree where all elements go to the right path in the binary search tree. These types of scenarios with skewed dataset will make the binary search tree highly in-efficient, where all kinds of operations will be very time-consuming. In addition to the search operation, the insertion or deletion operation will also take O(n) time complexity for the worst-case scenario. This type of situation will result in a totally unbalanced binary search tree, and the height of the tree is almost equal to the number of nodes in the tree. If we make sure that the height of the tree remains O(log n) after every insertion and deletion, then we can ensure an upper bound of O(log n) for all these operations, even for the worst-case scenario where the data is highly skewed. This is achieved by introducing the red-black tree, where the tree is always balanced irrespective of the data being skewed or non-skewed. The height of a red-black tree is always O(log n), where n is the number of nodes in the tree. By default, the red-black tree has the following properties, which are inherently available in the TreeMap dataset. Every node has references to the parent, right child, and left child node in the TreeMap. There can be these three references or reduced references in TreeMap if any node is not present. The left child element key will always have a lesser value compared to the parent element key value. The right child element key will always have a greater than or equal value compared to the parent element key value in TreeMap. Each tree node is colored either red or black. The root node of the tree is always black. Every path from the root to any of the leaf nodes must have the same number of black nodes. No two red nodes can be adjacent; i.e., a red node cannot be the parent or the child of another red node. If you see the table below, the time complexity is always the same for the red-black tree in any of the data scenarios, and it’s not impacted by the data skewness and always behaves consistently. This makes the TreeMap a very efficient and widely used data structure to deal with high volume data sets where we are not certain about the skewness of the underlying data in the dataset, and we can perform few unique kinds of operations on TreeMap which are not possible in other map data structures like HashMap. Time Complexity Operation Average Case Worst Case Search O(log n) O(log n) Insertion O(log n) O(log n) Deletion O(log n) O(log n) Search operation in case of extremely skewed data, which is the worst-case scenario to structure the data in a binary search tree, red-black tree works better for the worst-case scenario. Red-black trees can be used to efficiently index data in databases, allowing for techniques requiring fast search and retrieval of data. In this article, I am not going to explain the red-black algorithm in detail, but we will focus on a few of the niche functionalities provided by TreeMap, which is one prominent implementation of the red-black tree. Why Treemap Is Used TreeMap Class in Java provides a rich API with various kinds of search operations. It not only provides equal search operation where the element to be searched is present in the map but also other kinds of niche search operations like finding an element in the map which is next higher or next lower compared to the given element. Also, the submap of the map with element is the given range. These kinds of complex search operations are only possible if the keys are arranged in an order, and TreeMap is the data structure that is very apt to handle such processing requirements. The search operation usually takes O(log n) time to return the result. Unlike HashMap, which only takes a constant time, it takes a logarithmic time to perform the search operations. This makes one wonder why it was introduced in the first place. The answer is even if the search is faster for HashMap for scenarios that don’t fall in the worst-case category for HashMap to provide optimal search with constant time complexity, the data is saved in a memory in a contiguous manner. For TreeMap, there is no such limitation, and it only uses the amount of memory needed to hold/ store the items, unlike HashMap, which uses a contiguous region of memory. Another key reason, as discussed above, is TreeMap provides features to perform niche search operations, which is not always finding the given key in the map but finding other keys, which might be just the next higher, next lower, or the lowest key or a portion of the dataset for a given key range. Unlike HashMap, which provides only equal search operation where the value to be searched is equal to any key in the Map, TreeMap provides the ability to perform various kinds of search operations structured in the form of TreeMap. This ability to search makes TreeMap a very crucial data structure to solve complex search use cases, and I, in my experience, have used it extensively to solve many complex business requirements. Below are a few of the most prominent search functionalities provided by TreeMap. We will first make ourselves acquainted with the basic features provided by TreeMap and post that will discuss a few niche search requirements where we will bundle multiple features to arrive at a niche requirement for different kinds of search functionalities: floorKey(K key): This function searches for the key in the TreeMap, which is the greatest key less than or equal to the given key. If the function is not able to find any such key, it will return null. ceilingKey(K key): This function searches for the key in the TreeMap, which is the least key greater than or equal to the given key. If the function is not able to find any such key, it will return null. higherKey(K key): This function searches for the key in the TreeMap, which is the least key strictly greater than the given key. If the function is not able to find any such key, it will return null. lowerKey(K key) This function searches for the key in the TreeMap, which is the greatest key strictly less than the given key. If the function is not able to find any such key, it will return null. subMap(K from Key, K toKey): This function searches for the view of the portion of this map whose keys range from fromKey, inclusive, and toKey, exclusive. tailMap(K fromKey): This function searches for the view of the portion of this map whose keys are greater than or equal to fromKey. headMap(K toKey): This function searches for the key-value mapping associated with the least key strictly greater than the given key or null if there is no such key. Now we have gone through the key features and different kinds of search functionalities provided by a TreeMap, we will try to understand it better with code examples, and later we will try to define some new niche search and data structuring features using different combinations of the above listed TreeMap features: Use-Case We will be using the employee entity, which will be captured in the entity class below. This class has a few key employee traits for illustrating the use case. In the below employee class, in addition to employee identifier attributes, we are capturing a few additional distinct attributes that will be used in the use case. These attributes are as follows: lastYearRating: This holds the last year's appraisal rating for the employee. tenure: This holds the rounded number of years an employee has spent with the organization. currentSalary: This attribute stores the current annual salary of the employee. class Employee { String empName; String designation; Integer empId; String lastYearRating; Integer tenure; Integer currentSalary; public Employee(String empName, String designation, Integer empId, String lastYearRating, Integer tenure, Integer currentSalary) { this.empName = empName; this.designation = designation; this.empId = empId; this.lastYearRating = lastYearRating; this.tenure = tenure; this.currentSalary = currentSalary; } @Override public String toString() { return "Employee{" + "empName='" + empName + '\'' + ", designation='" + designation + '\'' + ", empId=" + empId + ", lastYearRating='" + lastYearRating + '\'' + ", tenure=" + tenure + ", currentSalary=" + currentSalary + '}'; } public Integer getCurrentSalary() { return currentSalary; } public void setCurrentSalary(Integer currentSalary) { this.currentSalary = currentSalary; } public String getEmpName() { return empName; } public void setEmpName(String empName) { this.empName = empName; } public String getDesignation() { return designation; } public void setDesignation(String designation) { this.designation = designation; } public Integer getEmpId() { return empId; } public void setEmpId(Integer empId) { this.empId = empId; } public String getLastYearRating() { return lastYearRating; } public void setLastYearRating(String lastYearRating) { this.lastYearRating = lastYearRating; } public Integer getTenure() { return tenure; } public void setTenure(Integer tenure) { this.tenure = tenure; } } In the below code illustrations, we will use TreeMap features to solve a few niche scenarios: We will bucket all the employees as per the tenure bucket for the organization: We will have six tenure buckets and will place every employee record in the right bucket they belong. This will use a few niche functions provided by TreeMap and will be depicted as being done in a very simplified manner. Next, we will associate the right tenure bucket to every employee. import java.util.ArrayList; import java.util.TreeMap; public class TreeMapCeilingFloorExample { public static void main(String[] args) { TreeMap<Integer, Object> tenureTreeMap = new TreeMap<>(); /* employee List, for illustration purpose just creating few dummy entries but in actual it can be read from source * and can run into very high numbers including all employees for the organization */ ArrayList<Employee> empList = new ArrayList<Employee>(); empList.add(new Employee("John", "Engineer", 24, "A1", 6,150000)); empList.add(new Employee("David", "Manager", 35, "A2", 3,145000)); empList.add(new Employee("Fred", "Architect", 41, "B1", 2, 155000)); empList.add(new Employee("Brad", "Engineer", 21, "A3", 8,120000)); empList.add(new Employee("Jason", "Engineer", 32, "A1", 4,170000)); empList.add(new Employee("Adam", "Senior Engineer", 12, "A1", 14,85000)); empList.add(new Employee("Christie", "Director", 10, "A1", 15,178000)); empList.add(new Employee("Martha", "Accountant", 26, "A1", 6,85000)); empList.add(new Employee("Diana", "Engineer", 28, "A1", 6,108000)); empList.add(new Employee("Lisa", "Developer", 14, "A1", 12,82000)); /* Adding the default buckets for the employee tenures with 0-5, 6- 10, 11-15, 16-20, 21-25, 26-30 * Adding only higher bound as key so can efficiently use ceiling function to categorize all employees into right bucket */ tenureTreeMap.put(5, new ArrayList<Employee>()); tenureTreeMap.put(10, new ArrayList<Employee>()); tenureTreeMap.put(15, new ArrayList<Employee>()); tenureTreeMap.put(20, new ArrayList<Employee>()); tenureTreeMap.put(25, new ArrayList<Employee>()); tenureTreeMap.put(30, new ArrayList<Employee>()); /* Using ceilingKey function to check for every employee record and adding the employee to the right bucket. * This is a simple illustration leveraging ceilingKey function to easily bucket employees into the right bucket */ empList.forEach(employeeObj -> { Integer key = tenureTreeMap.ceilingKey(employeeObj.getTenure()); ArrayList matchingList = (ArrayList) tenureTreeMap.get(key); matchingList.add(employeeObj); tenureTreeMap.put(key, matchingList); }); // Printing all Employees in the bucket starting with lowest to highest tenureTreeMap.forEach((key, value) -> { System.out.println("Key : " + key + " Value : "); ((ArrayList) value).forEach(empObj -> System.out.println()); }); } } Result Below is the depiction of the tenure TreeMap, where every employee is bucketed into the right tenure category. The key is the higher bound of the tenure bucket, and lower bound is the higher bound of the prior record+ 1. This is an efficient way to structure the data as per the given range. We are here having six tenure buckets as follows: 0 Year to 5 Year: For this range, the key is five, which is the upper bound of this bucket. Three employee records fall into this bucket. 6 Year to 10 Year: For this range, the key is ten, which is the upper bound of this bucket. Four employee records fall into this bucket. 11 Year to 15 Year: For this range, the key is 15, which is the upper bound of this bucket. Three employee records fall into this bucket. 16 Year to 20 Year: For this range, the key is 20, which is the upper bound of this bucket. No employee record falls into this bucket. 21 Year to 25 Year: For this range, the key is 25, which is the upper bound of this bucket. No employee record falls into this bucket. 26 Year to 30 Year: For this range, the key is 30, which is the upper bound of this bucket. No employee record falls into this bucket. Remember that the TreeMap uses the natural ordering of the keys (or a custom comparator if provided) to determine the order of elements. Make sure to import the TreeMap class and handle the cases where the methods return null if there's no suitable key according to your use case. The below code function associates the tenure range for every employee record. The result is also printed beneath the code, showing the tenure range for every employee record. The TreeMap is created with the key as the upper bound of the tenure range, and all the employees for the given tenure range are in the value corresponding to the given key in the form of an array list. The below-listed code uses ceiling and floor functions to find the lower bound and upper bound for any key in the TreeMap. In the below scenario, we are trying to find out the tenure range for every employee record by getting the lower bound using the lowerKey function. Next upper bound is determined using ceilingEntry method, and the range string is formed and associated with every employee record. This is a simple illustration to show the power of TreeMap functionality to easily accomplish complex requirements by leveraging the in-built functions. Result: In the below output, every employee has an associated tenure bucket associated with the record. Hope this article helped you to get acquainted with TreeMap data structure and helped with some scenarios to use the in-built TreeMap functions to solve complex data categorization and search requirements. I solved a few scenarios for the tenure use cases to bucket the data efficiently and use the bucketed data to perform complex search operations using TreeMap and a combination of in-built functions from TreeMap. I have added lastYearRating as well currentSalary attributes in the employee class. As a next step to gain some more hands-on experience working with TreeMap, please try to solve bucketing the data as per different salary buckets using TreeMap in-built functions and try to play around with different kinds of search operations on the TreeMap data bucketed as per salary range. Do let me know if you have any questions or need any further clarification on the topics discussed in this article.