Internal Developer Portals are reshaping the developer experience. What's the best way to get started? Do you build or buy? Tune in to see.
Agentic AI. It's everywhere. But what does that mean for developers? Learn to leverage agentic AI to improve efficiency and innovation.
Designing AI Multi-Agent Systems in Java
Spring Data Neo4j: How to Update an Entity
Observability and Performance
The dawn of observability across the software ecosystem has fully disrupted standard performance monitoring and management. Enhancing these approaches with sophisticated, data-driven, and automated insights allows your organization to better identify anomalies and incidents across applications and wider systems. While monitoring and standard performance practices are still necessary, they now serve to complement organizations' comprehensive observability strategies. This year's Observability and Performance Trend Report moves beyond metrics, logs, and traces — we dive into essential topics around full-stack observability, like security considerations, AIOps, the future of hybrid and cloud-native observability, and much more.
Getting Started With Agentic AI
Java Application Containerization and Deployment
DZone events bring together industry leaders, innovators, and peers to explore the latest trends, share insights, and tackle industry challenges. From Virtual Roundtables to Fireside Chats, our events cover a wide range of topics, each tailored to provide you, our DZone audience, with practical knowledge, meaningful discussions, and support for your professional growth. DZone Events Happening Soon Below, you’ll find upcoming events that you won't want to miss. Modernizing Enterprise Java Applications: Jakarta EE, Spring Boot, and AI Integration Date: February 25, 2025Time: 1:00 PM ET Register for Free! Unlock the potential of AI integration in your enterprise Java applications with our upcoming webinar! Join Payara and DZone to explore how to enhance your Spring Boot and Jakarta EE systems using generative AI tools like Spring AI and REST client patterns. What to Consider When Building an IDP Date: March 4, 2025Time: 1:00 PM ET Register for Free! Is your development team bogged down by manual tasks and “TicketOps”? Internal Developer Portals (IDPs) streamline onboarding, automate workflows, and enhance productivity—but should you build or buy? Join Harness and DZone for a webinar to explore key IDP capabilities, compare Backstage vs. managed solutions, and learn how to drive adoption while balancing cost and flexibility. DevOps for Oracle Applications with FlexDeploy: Automation nd Compliance Made Easy Date: March 11, 2025Time: 1:00 PM ET Register for Free! Join Flexagon and DZone as Flexagon's CEO unveils how FlexDeploy is helping organizations future-proof their DevOps strategy for Oracle Applications and Infrastructure. Explore innovations for automation through compliance, along with real-world success stories from companies who have adopted FlexDeploy. Make AI Your App Development Advantage: Learn Why and How Date: March 12, 2025Time: 10:00 AM ET Register for Free! The future of app development is here, and AI is leading the charge. Join Outsystems and DZone, on March 12th at 10am ET, for an exclusive Webinar with Luis Blando, CPTO of OutSystems, and John Rymer, industry analyst at Analysis.Tech, as they discuss how AI and low-code are revolutionizing development.You will also hear from David Gilkey, Leader of Solution Architecture, Americas East at OutSystems, and Roy van de Kerkhof, Director at NovioQ. This session will give you the tools and knowledge you need to accelerate your development and stay ahead of the curve in the ever-evolving tech landscape. Developer Experience: The Coalescence of Developer Productivity, Process Satisfaction, and Platform Engineering Date: March 12, 2025Time: 1:00 PM ET Register for Free! Explore the future of developer experience at DZone’s Virtual Roundtable, where a panel will dive into key insights from the 2025 Developer Experience Trend Report. Discover how AI, automation, and developer-centric strategies are shaping workflows, productivity, and satisfaction. Don’t miss this opportunity to connect with industry experts and peers shaping the next chapter of software development. What's Next? DZone has more in store! Stay tuned for announcements about upcoming Webinars, Virtual Roundtables, Fireside Chats, and other developer-focused events. Whether you’re looking to sharpen your skills, explore new tools, or connect with industry leaders, there’s always something exciting on the horizon. Don’t miss out — save this article and check back often for updates!
In this blog, we will explore what chat completion models can and cannot do and then see how Assistants API addresses those limitations. We will also focus on threads and messages — how to create them, list them, retrieve them, modify them, and delete them. Additionally, we will add some Python code snippets and show possible outputs based on the script language. Limitations of Chat Completion Models No Memory Chat completion models do not have a memory concept. For example, if you ask: “What’s the capital of Japan?” The model might say: “The capital of Japan is Tokyo.” But when you ask again: “Tell me something about that city.” It often responds with: “I’m sorry but you didn’t specify which city you are referring to.” It does not understand what was discussed previously. That’s the main issue: there is no memory concept in chat completions. Poor at Computational Tasks Chat completion models are really bad at direct computational tasks. For instance, if you want to reverse the string “openaichatgpt,” it may generate the wrong output, like inserting extra characters or missing some letters. No Direct File Handling In chat completions, there is no way to process text files or Word documents directly. You have to convert those files to text, do chunking (divide documents into smaller chunks), create embeddings, and do vector searches yourself. Only then do you pass some relevant text chunks to the model as context. Synchronous Only Chat completion models are not asynchronous. You must ask a question and wait for it to finish. You cannot do something else while it’s processing without extra workarounds. Capabilities of the Assistants API Context Support With Threads In Assistants API, you can create a thread for each user. A thread is like a chat container where you can add many messages. It persists the conversation, so when the user logs in again, you can pass the same thread ID to retrieve what was discussed previously. This is very helpful. Code Interpreter There is also a code interpreter. Whenever you ask for some computational task, it runs Python code. It then uses that answer to expand or explain. This makes it very helpful for reversing strings, finding dates, or any Python-based operations. Retrieval With Files The Assistants API has retrieval support, letting you upload files and ask questions based on those files. The system handles the vector search process and then uses relevant chunks as context. You can upload up to 20 files in Assistants as context. This is very helpful for referencing company documents, reports, or data sets. Function Calling Function calling allows the model to tell you what function to call and what arguments to pass, so that you can get external data (like weather or sales from your own database). It does not call the function automatically; it indicates which function to call and with what parameters, and then you handle that externally. Asynchronous Workflows The Assistants API is asynchronous. You can run a request, and you don’t have to wait for it immediately. You can keep checking if it’s done after a few seconds. This is very helpful if you have multiple tasks or want to do other things in parallel. Focusing on Threads and Messages A thread is essentially a container that holds all messages in a conversation. OpenAI recommends creating one thread per user as soon as they start using your product. This thread can store any number of messages, so you do not have to manually manage the context window. Unlimited messages. You can add as many user queries and assistant responses as you want.Automatic context handling. The system uses truncation if the conversation grows beyond token limits.Metadata storage. You can store additional data in the thread’s metadata (for example, user feedback or premium status). Below are code snippets to demonstrate how to create, retrieve, modify, and delete threads. 1. Creating an Assistant First, you can create an assistant with instructions and tools. For example: Python from openai import OpenAI client = OpenAI() file_input = client.files.create(file=open("Location/to/the/path", "rb"), purpose = "assistants") file_input.model_dump() Python assistant = client.beta.assistants.create( name="data_science_tutor", instructions="This assistant is a data science tutor.", tools=[{"type":"code_interpreter", {"type":"retrieval"}], model="gpt-4-1106-preview", file_ids=[file_input.id] ) print(assistant.model_dump()) 2. Creating Threads A thread is like a container that holds the conversation. We can create one thread per user. Python thread = client.beta.threads.create() print(thread.model_dump()) id – a unique identifier that starts with thr-object – always "thread"metadata – an empty dictionary by default Why Create Separate Threads? OpenAI recommends creating one thread per user as soon as they start using your product. This structure ensures that the conversation context remains isolated for each user. 3. Retrieving a Thread Python retrieved_thread = client.beta.threads.retrieve(thread_id=thread.id) print(retrieved_thread.model_dump()) This returns a JSON object similar to what you get when you create a thread, including the id, object, and metadata fields. 4. Modifying a Thread You can update the thread’s metadata to store important flags or notes relevant to your application. For instance, you might track if the user is premium or if the conversation has been reviewed by a manager. Python updated_thread = client.beta.threads.update( thread_id=thread.id, metadata={"modified_today": True, "user_is_premium": True} ) print(updated_thread.model_dump()) modified_today – a custom Boolean to note whether you changed the thread todayuser_is_premium – a Boolean flag for user account tierconversation_topic – a string that labels this thread’s main subject Further Metadata Examples {"language_preference": "English"} – if the user prefers answers in English or another language{"escalated": true} – if the thread needs special attention from a support team{"feedback_rating": 4.5} – if you collect a rating for the conversation 5. Deleting a Thread When you no longer need a thread, or if a user deletes their account, you can remove the entire conversation container: Python delete_response = client.beta.threads.delete(thread_id=thread.id) print(delete_response.model_dump()) Once deleted, you can no longer retrieve this thread or any messages it contained. Working With Messages Previously, we focused on threads — the containers that hold conversations in the Assistants API. Now, let’s explore messages, which are the individual pieces of content (questions, responses, or system notes) you add to a thread. We’ll walk through creating messages, attaching files, listing and retrieving messages, and updating message metadata. We’ll also show Python code snippets illustrating these steps. Messages and Their Role in Threads What Are Messages? Messages are mostly text (like user queries or assistant answers), but they can also include file references. Each thread can have many messages, and every message is stored with an ID, a role (for example, "user" or "assistant"), optional file attachments, and other metadata. Opposite Index Order Unlike chat completions, where the first message in the list is the earliest, here, the first message you see in the array is actually the most recent. So, index 0 corresponds to the newest message in the thread. Annotations and File Attachments Messages can include annotations, for instance, if a retrieval step references certain files. When using a code interpreter, any new files generated may also appear as part of the message annotations. Create a Message in a Thread Messages are added to a thread. Each message can be a user message or an assistant message. Messages can also contain file references. Before adding messages, we need a thread. If you do not already have one: Python # Create a new thread new_thread = client.beta.threads.create() print(thread.model_dump()) # Shows the thread's detailspython Python # Create a new message in the thread message = client.beta.threads.messages.create( thread_id=thread.id, role="user", content="ELI5: What is a neural network?", file_ids=[file_input.id] # Passing one or more file IDs ) print(message.model_dump()) Here, you can see: Message ID – unique identifier starting with msgRole – user, indicating this is a user inputFile attachments – the file_ids list includes any referenced filesAnnotations – empty at creation, but can include details like file citations if retrieval is involvedMetadata – a placeholder for storing additional key-value pairs List Messages in a Thread To list messages in a thread, use the list method. The limit parameter determines how many recent messages to retrieve. Now, let’s try to list all the messages: You will see only the most recent messages. For instance, if we’ve added just one message, the output will look like: Python messages_list = client.beta.threads.messages.list( thread_id=thread.id, limit=5 ) for msg in messages_list.data: print(msg.id, msg.content) If there are multiple messages, the system works like a linked list: The first ID points to the newest message.The last ID points to the earliest message. Retrieve a Specific Message Python retrieved_msg = client.beta.threads.messages.retrieve( thread_id=new_thread.id, message_id=message.id ) print(retrieved_msg.model_dump()) Retrieve a Message File Now, let’s retrieve a message file: This provides the file’s metadata, including its creation timestamp. Python files_in_msg = client.beta.threads.messages.files.list( thread_id=new_thread.id, message_id=message.id ) print(files_in_msg.model_dump()) Modify a Message Python updated_msg = client.beta.threads.messages.update( thread_id=new_thread.id, message_id=message.id, metadata={"added_note": "Revised content"} ) print(updated_msg.model_dump()) Delete a Message Python deleted_msg = client.beta.threads.messages.delete( thread_id=new_thread.id, message_id=message.id ) print(deleted_msg.model_dump()) We have seen that chat completion models have no memory concept, are bad at computational tasks, cannot process files directly, and are not asynchronous. Meanwhile, Assistants API has context support with threads, code interpreter for computational tasks, retrieval for files, function calling for external data, and it also supports asynchronous usage. In this blog, we focused on how to create, list, retrieve, modify, and delete threads and messages. We also saw how to handle file references within messages. In the next session, we will learn more about runs, which connect threads and assistants to get actual outputs from the model. I hope this is helpful. Thank you for reading! Let’s connect on LinkedIn! Further Reading Where did multi-agent systems come from?Summarising Large Documents with GPT-4oHow does LlamaIndex compare to LangChain in terms of ease of use for beginnersPre-training vs. Fine-tuning [With code implementation]Costs of Hosting Open Source LLMs vs Closed Sourced (OpenAI)Embeddings: The Back Bone of LLMsHow to Use a Fine-Tuned Language Model for Summarization
SQL Server Dynamic Data Masking is a feature that allows you to obscure sensitive data from non-privileged accounts, improving data security and compliance. Rather than showing credit card numbers, passwords, or personal identifiers in cleartext, you can define masking rules at the column level so that specific users see only masked values. In contrast, others with elevated permissions see the actual data. When to Use Dynamic Data Masking Lower environments (development, QA). Typically, developers and testers do not need access to actual sensitive information. Masking ensures that they can work with realistic datasets without risking exposure to PII.Third-party access. When sharing data with external consultants or analytics vendors, masked data prevents inadvertent or malicious disclosure of sensitive content.Regulatory compliance. For environments where regulations like GDPR, HIPAA, or PCI-DSS apply, dynamic masking helps ensure only authorized personnel can view sensitive data in cleartext Prerequisites SQL server version. Dynamic data masking is available in SQL Server 2016 and later.Permissions and roles. To create or modify masking rules, you must have the ALTER ANY MASK and ALTER permissions on the table. End-users who only have SELECT permissions on the table or view will automatically be served masked data if they do not have UNMASK permission.Assessment of sensitive fields. Identify which columns contain PII or sensitive data. Typical candidates: Email addressesPhone numbersNational identifiers (e.g., SSN)Credit card numbersPasswords or security answers How to Implement Dynamic Data Masking 1. Identify Columns to Mask Review each column and decide which requires masking using the query below: MS SQL SELECT TABLE_NAME, COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'Customers' ORDER BY TABLE_NAME, COLUMN_NAME; 2. Choose a Masking Function SQL Server provides a few built-in masking functions: Default() – masks the entire value using a default value depending on the data typeEmail() – masks the email format (e.g., xxx@example.com)Partial (prefix, padding, suffix) – allows partial masking of a string. For example, it shows the first character, masks the middle, and shows the last character.Random ([start range], [end range]) – for numeric columns, a random number in the specified range is returned. Example Masking Scenarios Name fields (e.g., FirstName, LastName). Use partial() to show maybe the first letter and mask the rest.Email address. Use email() for a consistent masked pattern.Credit card number. Use partial() to show only the last four digits.Password columns. Use default() to mask fully. 3. Apply Masking to the Table For example, consider a Customers table with columns: FirstName, LastName, Email, CreditCardNumber, and Password. Below are some sample queries: MS SQL -- Mask the first name to show only the first letter ALTER TABLE Customers ALTER COLUMN FirstName ADD MASKED WITH (FUNCTION = 'partial(1, "****", 0)'); -- Mask the last name similarly ALTER TABLE Customers ALTER COLUMN LastName ADD MASKED WITH (FUNCTION = 'partial(1, "*****", 0)'); -- Mask the email using built-in email masking ALTER TABLE Customers ALTER COLUMN Email ADD MASKED WITH (FUNCTION = 'email()'); -- Mask credit card number to show only the last 4 digits ALTER TABLE Customers ALTER COLUMN CreditCardNumber ADD MASKED WITH (FUNCTION = 'partial(0,"****-****-****-",4)'); -- Mask the password fully ALTER TABLE Customers ALTER COLUMN Password ADD MASKED WITH (FUNCTION = 'default()'); Important: You must be a member of the db_owner role or have the ALTER ANY MASK permission in the database. 4. Create a Non-Privileged User or Role to Test Masking Use the below queries: MS SQL CREATE USER MaskedUser WITHOUT LOGIN; GRANT SELECT ON Customers TO MaskedUser; When MaskedUser queries the table: EXECUTE AS USER = 'MaskedUser'; SELECT FirstName, LastName, Email, CreditCardNumber, Password FROM Customers; REVERT; They will see masked data. If an administrator with the UNMASK permission runs the same query, they will see the real data. 5. Monitoring and Verification Data audits. Regularly audit queries and logins to ensure no unauthorized UNMASK permissions are granted.Test masking patterns. Confirm that the masked output meets your compliance and business requirements. For instance, ensure the displayed format (like ****-****-****-1234 for a credit card) is correct.Documentation. Maintain a data dictionary or schema documentation that notes which columns are masked and how so that team members understand what they see in downstream environments. Example Result Original data (Admins with UNMASK): FirstNameLastNameEmailCreditCardNumberPasswordAliceNadellaalice.n@example.com4111-1111-1111-1231MySecretPass%JohnYesujohn.y@example.com5555-6666-7777-8899Password123$ View for Non-Privileged Users: FirstNameLastNameEmailCreditCardNumberPasswordA****S*****xxx@xxxx.com****-****-****-1234****J****D*****xxx@xxxx.com****-****-****-8888**** Conclusion Implementing Dynamic Data Masking in SQL Server is one meaningful step towards what many people have begun to call 'privacy-first' architecture. In any case, the implementation will align with basic data protection principles, such as under GDPR and CCPA, allowing only correctly authorized users to see sensitive data in full view. In contrast, other users get values either masked or partially to decrease the possibility of unauthorized disclosure of personal information. Data Minimization and Access Control GDPR and CCPA are based on data minimization, meaning they only provide the data necessary for a particular task. Dynamic masking ensures that you show only the minimal, masked version of sensitive data to non-privileged roles, thus adhering to these regulations. Improved Protection and Exposure Reduction It minimizes the risk of personal data exposure by storing sensitive data in masked form within the databases while processing. Should unauthorized access or a data breach at the application/reporting layer occur, the data already shown is masked. Therefore, such an event would have minimal impact on the subjects. Audit and Compliance Readiness Well-documented masking rules and role-based permissions support the accountability principle of GDPR and the transparency requirements of CCPA. Auditors can easily verify that your organization has technical measures to safeguard personal information, helping demonstrate compliance and due diligence. Ease of Implementation in Development and Testing For lower environments, where developers and testers often need "realistic" data, dynamic masking provides a systematic way to ensure personal information is never exposed. This approach helps maintain privacy protections throughout the data lifecycle. Scalability and Consistency Because data masking is dynamic and at the database layer, it scales to multiple applications, services, and analytic tools. This uniformity supports clearly outlined compliance policies and reduces the chance of policy drift or mistakes in bespoke masking logic at different codebases. Incorporating dynamic data masking into your general privacy-by-design strategy allows you to protect data subjects' privacy interests while lowering the risks of regulatory fines and engendering better customer trust. This fits within the GDPR's focus on privacy by design and by default, and the CCPA demands reasonable security measures to safeguard consumer data.
Are you looking for a user-friendly, self-hosted AI interface designed to operate entirely offline? Look no further; Open WebUI might be what you are looking for. In this blog, you will dive into some nice features of Open WebUI. Enjoy! Introduction Quite some inference engines exist which can run locally, for example, Ollama, LMStudio, LocalAI, Jan, and many others. Some of them also come with a Graphical User Interface (GUI). However, these run locally on the same machine as the inference engine. What if you would like to offer a ChatGPT-like user interface within your company that runs entirely offline? The inference engine runs on dedicated machines with GPUs (on-premise or in a private cloud), and the GUI is a web application available to your users. The advantage of this setup is that all your data does not leave your company and is not shared with any cloud vendor. The privacy of your data is secured with this setup. The disadvantage is that you might not be able to run large models and that you need to make a trade-off between quality and performance. However, Exo and JLama are initiatives that are working on AI clustering, which will make it possible to run large models locally. It is just a matter of time before this functionality will be available. In the meanwhile, Open WebUI provides you with a web application that offers quite some functionality to run your AI solution entirely offline. Let’s explore some of its features in this blog. Check out the official documentation of Open WebUI, which is not complete but offers good information about its features. Sources used in this blog are available on GitHub. Prerequisites Prerequisites for reading this blog are: Basic knowledge of Docker and Docker Compose;Basic knowledge of large language models (LLMs);Basic knowledge of retrieval-augmented generation (RAG). More info can be found in a previous blog. 3. Installation Several methods are available for installing Open WebUI. In this section, the setup with a locally running Ollama instance is described together with Open WebUI running in a Docker container. For ease of use, the Docker command is converted to a compose.yaml file. YAML version: '3' services: open-webui: image: ghcr.io/open-webui/open-webui:main container_name: open-webui ports: - "3000:8080" volumes: - open-webui:/app/backend/data volumes: open-webui: Start the container from where the compose file is located. Shell $ docker compose up After startup, Open WebUI is accessible via http://localhost:3000/. Create an admin account. After a successful login, the webpage shows a blank screen. After approximately 5 minutes, an error occurs in the logs. Plain Text open-webui | ERROR [open_webui.routers.ollama] Connection error: Cannot connect to host host.docker.internal:11434 ssl:default [Connect call failed ('172.17.0.1', 11434)] After this error, the release notes were shown. However, it was not possible to select a model, although models are available in the locally running Ollama instance. Shut down the container with CTRL+C or by entering the command: Shell $ docker compose down Apparently, Open WebUI is not able to access the running Ollama instance on the host. Therefore, you can bind the container to your host network, as described here. The compose file becomes the following. YAML version: '3' services: open-webui: image: ghcr.io/open-webui/open-webui:main container_name: open-webui network_mode: host volumes: - open-webui:/app/backend/data environment: - OLLAMA_BASE_URL=http://localhost:11434 volumes: open-webui: Start the container again. Shell $ docker compose up Note that Open WebUI is now accessible via http://localhost:8080/. My First Prompt Ollama already contains some models. If you have not installed any, you can install llama3.2:3b which is a small and good model to start with. Shell $ ollama pull llama3.2:3b Now that the connection with Ollama is working, you will see all available models in Open WebUI. As a first prompt, you ask the model to tell a joke. And the model returns a joke. This works quite similarly to any other AI service, but the difference is here that everything is running locally. No data is sent outside of your laptop! Knowledge A very interesting feature is the knowledge feature. This allows you to add your own documents as context to the model. It is, in fact, retrieval-augmented generation (RAG). You can add your documents by clicking the workspace in the left menu. This will show you some tabs under the Knowledge tab. In a previous blog, RAG was implemented and evaluated by using three markdown documents containing data in table format about songs and albums of Bruce Springsteen. Let’s add these documents. Click the +-sign at the right to create a new knowledge base. Drag and drop each file to the knowledge base. Be patient and add the next file while the processing of the current one is finished. Otherwise, the browser might crash. Now that the knowledge base is created, let’s evaluate the responses based on the following questions and answers. on which album was “adam raised a cain” originally released? The answer is “Darkness on the Edge of Town”.what is the highest chart position of “Greetings from Asbury Park, N.J.” in the US? This answer is #60.what is the highest chart position of the album “tracks” in canada? The album did not have a chart position in Canada.in which year was “Highway Patrolman” released? The answer is 1982.who produced “all or nothin’ at all”? The answer is Jon Landau, Chuck Plotkin, Bruce Springsteen and Roy Bittan. Navigate to the chat window and type a hash (#). A popup window is shown where you can select a knowledge base. Select the brucespringsteen collection. Now, you can start asking the questions from above. Question 1 The answer is correct. Also, note that the source where the information is found is mentioned. This is very convenient, as you will notice shortly. At the bottom, some controls are available to copy the response, to read the response aloud, to retrieve some information like token usage, and so on. Question 2 The response to question 2 is correct. According to the context provided, the song “Greetings from Asbury Park, N.J.” by Bruce Springsteen had a chart position of 60 in the US. Question 3 This question is a tricky one because an album called Tracks exists, but also an album called Tracks 18. Besides that, the album Tracks did not chart at all in Canada. The response is not wrong, but also not entirely correct. However, you can take a look at the sources and verify the response. Unfortunately, I don’t have information on the specific chart performance of the album “Tracks” in Canada from the provided context. Can you please provide more information or clarify what’s being asked? Question 4 The response to question 4 is correct. According to the context provided, “Highway Patrolman” by Bruce Springsteen was released in 1982. Question 5 The answer to question 5 is not correct. I’m not aware of any information about a song called “All or Nothin’ at All.” The context only mentions that it is part of the album “Human Touch” by Bruce Springsteen, but it doesn’t specify who produced it. Take a closer look at the sources. When adding a document to the knowledge base, the document is split into chunks. Because the documents contain tables, the header information is lost in many chunks, and therefore, the meaning of each cell is lost. That is probably why the correct chunk scores lower than 50%, and the model thinks this information is not relevant. Considering all responses, the result is certainly not bad because tables are quite challenging to use in RAG. The results in the previous blog were better, but there custom chunking was applied. Do note that in both cases the same model has been used. Web Search Another way to enrich the prompt with extra information is to add web pages. Create a new chat window, and just like adding documents, you can add a web page by typing a hash (#) and typing or pasting a web URL. Again, a popup window is shown, where you can select and add the web page. This works similarly to the knowledge you saw earlier. Add a previous blog: https://dzone.com/articles/why-mvn-install-may-risk-your-builds. Prompt to create a summary. The response is not correct. The blog is about Maven, but the summary is entirely wrong. Response Based on the provided context, it appears that the user is asking me to summarize the output of a Maven build process. From the context, it seems like there were two builds executed: one that was successful and another that failed due to dependency issues. The successful build took around 1 second to complete, while the failed build took significantly less time (0.175 seconds). The failed build had dependency issues, as indicated by the “FAILURE” message. However, without more specific information about what the user wants me to summarize (e.g., specific errors or metrics), it’s difficult to provide a more detailed summary. Can you please clarify what kind of summary you’re looking for? Are there any specific aspects of the build output you’d like me to highlight? Second attempt with the following prompt: Create a summary of the added blog post. Again, the model does not seem to understand what is asked for. Response Unfortunately, I don’t have enough information about the content of the added blog post. The provided context appears to be from a developer’s blog or website, but it doesn’t include any details about the actual blog post being referred to. Could you please provide more context or information about what the blog post is about? Is it related to Maven, Java development, or something else entirely? I’ll do my best to summarize the content based on your query. The third attempt is to explicitly add the link in the prompt (and add please :-)): Please create a summary of the blog https://mydeveloperplanet.com/2024/11/20/why-mvn-install-may-risk-your-builds/. This response is not entirely correct, but it is not wrong either. However, adding the link to the prompt did make a difference. In order to get a better result, you could change the underlying model. Anyway, Open WebUI did the job well. Response The blog post “Why ‘mvn install’ May Risk Your Builds” discusses potential risks associated with using the mvn install command in Maven build processes. According to the author, mvn install can cause issues when used on feature branches or branches that are not intended for production. This is because mvn install downloads and installs dependencies from the repository into the local Maven cache, which can lead to: Unfinished work being promoted to a more stable branch without proper testing.Dependencies from unstable features being installed in production environments. The author recommends using mvn verify instead of mvn install, as it verifies the build and checks for any dependencies issues before proceeding. Additionally, the blog post discusses the importance of considering separate stages in a build pipeline and using commands like rm -r ~/.m2/repository/com/mydeveloperplanet/mymavenverifyinstallplanet/ to clean up the local Maven repository between builds. Overall, the author aims to highlight the potential risks of relying on mvn install in certain situations and provide guidance on how to mitigate these risks. Knowledge PDF You can also add PDF documents to the knowledge base. Let’s find out whether information from a PDF can be retrieved. Again, information about Bruce Springsteen will be prompted. The following prompt will be used. The expected response is shown also. Who was Bruce Springsteen married to? Bruce Springsteen has been married to Julianne Phillips and to Patti Scialfa. First, let’s ask llama3.2 this question to see what the model knows already. The answer is partially correct. Patti Scialfa is mentioned, but not Julianne Phillips.The names of the children are correct, but none of the dates are correct. Response Bruce Springsteen has been married to Patti Scialfa since October 6, 1991. They have three children together: Evan James Springsteen (born March 25, 1990), Jessica Rae Springsteen (born April 30, 1992), and Sam Ryan Springsteen (born August 5, 2003). The information about his personal life can be found on the Bruce Springsteen Wikipedia page. The page is downloaded as a PDF and added to a new knowledge base, brucewiki. Prompt the question while adding this knowledge base. The answer is not better. He has been married twice, but Julianne Phillips is not mentioned again.Patti Scialfa was his second wife, not his first.The name of the second wife is made up.The names of the other ladies are correct. Response According to various sources, Bruce Springsteen has been married twice: his first wife, Patti Scialfa, whom he married in 1997 and divorced in 2009his second wife, actress Ponselle, but this information is not found in the provided context. However, it’s worth noting that Bruce Springsteen also dated photographer Lynn Goldsmith and model Karen Darvin, as well as actress Joyce Hyser, in the past. If you’re looking for more specific information on his marriages or relationships, I’d be happy to try and help further. Just for fun, let’s see what a web search returns as a response. Add the Wikipedia link and use the following prompt: Who was Bruce Springsteen married to, use the information from https://en.wikipedia.org/wiki/Bruce_Springsteen. The response is getting better. Springsteen did not divorce from Patti Scialfa, though.This time, Julianne Phillips is mentioned.The dates are wrong again. Response According to Wikipedia, Bruce Springsteen was married to Patti Scialfa from 1997 to 2015 [1]. They were together for over 18 years before their divorce. Before marrying Patti, he was married to Julianne Phillips from 1983 to 1989. It’s worth noting that his ex-wife Patti Scialfa has been a significant influence on his music and career, and has also pursued a successful music career in her own right. Controls At the top right corner, you can set some Controls. The System Prompt and Temperature are typically items you would like to change and control now and then. Be aware that you have this possibility. Admin Panel When you are an admin user, you can click your account, and you will be able to select the Admin Panel. You can add roles, set up LDAP, and many other administration tasks can be configured here. Conclusion Open WebUI is a very feature-rich UI that works entirely offline. As seen in the previous examples, using RAG has some issues, but this has nothing to do with Open WebUI. You can add custom logic to improve the results using Pipes. Besides that, you can experiment with different models and change parameters in order to improve the results.
Microsoft CEO Satya Nadella recently announced that GitHub Copilot is now free for all developers in VSCode. This is a game-changer in the software development industry. Github Copilot is an AI code assistant that helps developers finish their coding tasks easily and quickly. It also helps suggest code snippets and autocomplete functions. In this article, we will learn how to use GitHub Copilot using VSCode in a step-by-step manner for creating the first stateless flask microservice. This is a beginner-friendly guide showcasing how Copilot helps reduce the development time and simplify the process. Setting Up the Environment Locally As our primary focus will be on GitHub Copilot, I will write a high level on the software installation needed. If any installation issues are seen, it is expected that readers would have to solve them locally or comment in this article, where I can try to help. 1. Install Visual Studio Code on Mac or Windows from VSCode (In my examples, I used Mac). 2. Install GitHub Copilot extension in VSCode: Open VSCode and navigate to the Extensions view on the left, as per the below screenshot. Search for "copilot," and GitHub Copilot will appear. Click install. With this step, the Copilot extension is added to VSCode. 3. Activate the Copilot: If you do not have a GitHub account, please create one in GitHub.Back to VSCode, after installing Copilot, we can see in the Welcome tab that it will ask to sign up. Sign up using a GitHub account. Click "Chat with Copilot," and you will see the right side of VSCode, Copilot appears. Click "Chat with Copilot." We will see that the Copilot chat appears on the right-hand side of the VSCode palate. 4. Install Python in your system from Python based on Windows/Mac. Note that we are not installing Flask now; we will do it in a later step while installing the application to run. Writing the Microservice Using CoPilot 1. In VSCode, on the right side with the Copilot pallet, under "Ask Copilot," type: Create a Flask app. There are two ways we can ask Copilot. One is to create the Flask project folder with files and ask Copilot to add the code. Or, start from nothing and ask to create a Flask app. We notice that it will create a workspace for us along with all file creation, which is awesome, and the project gets created with the required files within a few seconds. Click -> Create Workspace -> give the location to save the project. The project will appear in VSCode. 2. We see that the project-created files will have routes.py, where a few default APIs are already generated. Now, we will create 2 APIs using Copilot. The first API is simple and used to greet a person. It takes the name of the person as input and out as "Hello, {name}." Open the routes.py file and add a comment as below: As soon as we hit enter, we see the code generated. Now press the tab, and we will see that the API code is generated. That's the advantage of using Copilot. Similarly, let's create another simple API that takes two integer values as input and returns the multiplication by using Copilot. This time we will try it in the right pallet of VSCode rather than in the routes.py file. Python # Create an endpoint to multiply two numbers. @main.route('/multiply') def multiply(): try: num1 = float(request.args.get('num1')) num2 = float(request.args.get('num2')) result = num1 * num2 return f'The result of {num1} * {num2} is {result}' except (TypeError, ValueError): return 'Invalid input. Please provide two numbers as query parameters.' However, I see a different code was generated when I asked Copilot to write the API inside the routes.py file. See below: Python # Create an endpoint to multiply two numbers. @main.route('/multiply/<int:num1>/<int:num2>') def multiply(num1, num2): return f'{num1} * {num2} = {num1 * num2}' The reason here is based on the previous context it generates the code. When we were on the routes.py file and asked the Copilot to generate the API code, it generated based on the context that the API should have two inputs and return the output. But when we requested to generate in the right palate, it generated based on the previous question with the context that it's a flak app, and input will come from the request param. So here, we can safely conclude that based on previous context, it will generate the next output. Now, both our APIs are ready, so let's deploy the app and test it. But we have not installed Flask yet. So, let's do that. 1. Activate the virtual environment and install Flask. Plain Text source venv/bin/activate # On Linux/Mac venv\Scripts\activate # On Windows pip install flask When we run the application, we see an issue in the startup due to the generated code. Below is the error: Plain Text File "/Users/sibasispadhi/Documents/coding/my-flask-app/venv/lib/python3.12/site-packages/flask/cli.py", line 72, in find_best_app app = app_factory() ^^^^^^^^^^^^^ File "/Users/sibasispadhi/Documents/coding/my-flask-app/app/__init__.py", line 14, in create_app app.register_blueprint(routes.bp) ^^^^^^^^^ AttributeError: module 'app.routes' has no attribute 'bp' (venv) sibasispadhi@Sibasiss-Air my-flask-app % The create_app function in our project's app/__init__.py file is calling app.register_blueprint(routes.bp), but the routes.py file doesn’t have bp (Blueprint object) defined. Below are the changes done to fix the problem. (See the code commented is the one autogenerated). Python # Register blueprints from . import routes # app.register_blueprint(routes.bp) app.register_blueprint(routes.main) Re-running the application will successfully deploy the application, and we are ready to test the functionality. The APIs can be tested using Postman. 2. Testing through Postman gives the results successfully. Conclusion GitHub Copilot generates the project and the boilerplate code seamlessly and it saves development time and effort. It's always advised to review the generated code so that it matches developers' expectations. Whenever there is an error, we must debug or request Copilot further suggestions to solve the problem. In this project, Copilot helped us create and run a stateless Flask microservice in no time. We faced some initial hiccups, which were solved after debugging, but overall, the development time was faster. I would suggest all readers start exploring Copilot today and enhance their day-to-day productivity. Stay tuned for my next set of articles on Copilot, where we will dive deep into more real-world scenarios and see how it solves our day-to-day tasks in a smooth manner.
As the Trump administration revokes Executive Order 14110, the U.S. shifts toward a market-driven AI strategy, departing from the Biden administration’s regulatory framework. While proponents see this as a catalyst for innovation and economic growth, critics warn of increased risks, regulatory fragmentation, and strained transatlantic relations. With Europe reinforcing its AI Act and states like California exploring their own regulations, the future of AI governance in the U.S. remains uncertain. Will deregulation accelerate progress, or does it open the door to new challenges in ethics, security, and global cooperation? Just days after taking office, Donald Trump, the 47th President of the United States, issued a series of executive actions aimed at dismantling key initiatives from the Biden administration. Among them was the revocation of Executive Order (EO) 14110, a landmark policy that established a framework for AI governance and regulation. This decision marks a turning point in U.S. AI policy. For its supporters, it is a necessary reform; for its critics, it is a dangerous setback. While EO 14110 aimed to structure AI adoption by balancing innovation and oversight, its repeal raises critical questions about the future of AI in the United States and its global impact. Background on Executive Order 14110 Executive Order 14110 was issued on October 30, 2023, under the Biden administration. This major initiative aimed to regulate the development and deployment of artificial intelligence. Its goal was to balance innovation, security, and economic stability while ensuring that AI systems remained reliable, safe, and transparent. In the Biden administration’s vision, EO 14110 was designed to address key concerns such as algorithmic bias, misinformation, job displacement, and cybersecurity vulnerabilities. It was not intended to impose direct restrictions on the private sector but rather to establish security and ethical standards, particularly for AI used by federal agencies and in public sector contracts, while also influencing broader AI governance. From an international perspective, EO 14110 also aimed to strengthen the United States' role in global AI governance. It aligned with the European Union’s approach, particularly as the EU was developing its AI Act. The order was part of a broader transatlantic effort to establish ethical and security standards for AI. "Artificial Intelligence (AI) holds extraordinary potential for both promise and peril. Responsible AI use has the potential to help solve urgent challenges while making our world more prosperous, productive, innovative, and secure. At the same time, irresponsible use could exacerbate societal harms such as fraud, discrimination, bias, and disinformation; displace and disempower workers; stifle competition; and pose risks to national security." (EO 14110 - Section 1) EO 14110 as Part of a Broader AI Strategy: Continuity in Biden’s Policy It is important to understand that EO 14110 was not an isolated initiative. It was part of a broader strategy built on several existing frameworks and commitments. Blueprint for an AI Bill of Rights (2022). A foundational document outlining five key principles: safe and effective AI systems, protections against algorithmic discrimination, data privacy, transparency, and human alternatives. Voluntary AI Commitments (2023-2024). Major tech companies, including Google, OpenAI, and Microsoft, agreed to self-regulation measures focusing on AI transparency, security, and ethics. National Security AI Strategy (2024). The Biden administration made AI a priority in cybersecurity, military applications, and critical infrastructure protection. It is worth noting that even after the revocation of EO 14110, these initiatives remain in place, ensuring a degree of continuity in AI governance in the United States. Objectives and Scope of EO 14110 Executive Order 14110 pursued several strategic objectives aimed at regulating AI adoption while promoting innovation. It emphasized the security and reliability of AI systems by requiring robustness testing and risk assessments, particularly in sensitive areas such as cybersecurity and critical infrastructure. It also aimed to ensure fairness and combat bias by implementing protections against algorithmic discrimination and promoting ethical AI use in hiring, healthcare, and justice. EO 14110 included training, reskilling, and protection programs to help workers adapt to AI-driven changes. It also aimed to protect consumers by preventing fraudulent or harmful AI applications, ensuring safe and beneficial use. Finally, the executive order aimed to reinforce international cooperation, particularly with the European Union, to establish common AI governance standards. However, it’s important to note that it did not aim to regulate the entire private sector but rather to set strict ethical and security standards for AI systems used by federal agencies. Summary of EO 14110’s Key Principles To quickly get the essentials, here are the eight fundamental principles it was built on: Ensure AI is safe and secure.Promote responsible innovation and competition.Support workers affected by AI’s deployment.Advance equity and civil rights.Protect consumer interests in AI applications.Safeguard privacy and civil liberties.Enhance AI capabilities within the federal government.Promote U.S. leadership in global AI governance. Why Did the Trump Administration Revoke EO 14110? So, on January 20, 2025, the Trump administration announced the revocation of EO 14110, arguing that it restricted innovation by imposing excessive administrative constraints. The White House justified this decision as part of a broader push to deregulate the sector, boost the economy, and attract AI investment. The administration made clear its preference for a market-driven approach. According to Trump, private companies are better positioned to oversee AI development without federal intervention. Clearly, this shift marks a geopolitical turning point. The United States is moving away from a multilateral approach to assert its dominance in the AI sector. However, this revocation does not mean the end of AI regulation in the United States. Other federal initiatives, such as the NIST AI Risk Management Framework, remain in place. "Republicans support AI development rooted in free speech and human flourishing." (The 2024 Republican Party by Reuters) Consequences of the Revocation in the United States The repeal of EO 14110 has immediate effects and long-term implications. It reshapes the future of AI development in the United States. From the Trump administration’s perspective, this decision removes bureaucratic hurdles, accelerates innovation, and strengthens U.S. competitiveness in AI. Supporters argue that by reducing regulatory constraints, the repeal allows companies to move faster, lowers compliance costs, and attracts greater investment, particularly in automation and biotechnology. But on the other hand, without a federal framework, the risks associated with the development and use of AI technologies are increasing. Algorithmic bias, cybersecurity vulnerabilities, and the potential misuse of AI become harder to control without national oversight. Critics also warn of a weakening of worker and consumer protections, as the end of support programs could further deepen economic inequalities. In practical terms, regulation is becoming more fragmented. Without a federal framework, each state could, and likely will, develop its own AI laws, making compliance more complex for businesses operating nationwide. Some see this as an opportunity for regulatory experimentation, while others see it as a chance for opportunistic players to exploit loopholes or fear legal uncertainty and increased tensions with international partners. Impact on Europe The revocation of EO 14110 also affects global AI governance, particularly in Europe. Transatlantic relations are likely to become strained, as the growing divergence between U.S. and European approaches will make regulatory cooperation more challenging. European companies may tighten their compliance standards to maintain consumer trust, which could influence their strategic decisions. In fact, the European Union may face pressure to adjust its AI Act, although its regulatory framework remains largely independent from that of the United States. Conclusion The revocation of Executive Order 14110 is more than just a policy shift in the United States. It represents a strategic choice, favoring a deregulated model where innovation takes precedence over regulation. While this decision may help accelerate technological progress, it also leaves critical questions unanswered: Who will ensure the ethics, security, and transparency of AI in the United States? For Europe, this shift deepens the divide with the U.S. and strengthens its role as a "global regulator" through the AI Act. The European Union may find itself alone at the forefront of efforts to enforce strict AI regulations, risking a scenario where some companies favor the less restrictive U.S. market. More than a debate on regulation, this revocation raises a fundamental question: In the global AI race, should progress be pursued at all costs, or should every advancement be built on solid and ethical foundations? The choices made today will shape not only the future of the industry but also the role of democracies in the face of tech giants. One More Thing The revocation of EO 14110 highlights a broader debate: who really shapes AI policy, the government or private interests? While the U.S. moves toward deregulation, California’s AI safety bill (SB 1047) is taking the opposite approach, proposing strict oversight for advanced AI models. But as an investigation by Pirate Wires reveals, this push for regulation isn’t without controversy. Dan Hendrycks, a key advocate for AI safety, co-founded Gray Swan, a company developing compliance tools that could directly benefit from SB 1047’s mandates. This raises a crucial question: When policymakers and industry leaders are deeply intertwined, is AI regulation truly about safety, or about controlling the market? In the race to govern AI, transparency may be just as important as regulation itself.
Neon is now available on the Azure marketplace. The new integration between Neon and Azure allows you to manage your Neon subscription and billing through the Azure portal as if Neon were an Azure product. Azure serverless and Neon are a natural combination — Azure serverless frees you from managing your web server infrastructure. Neon does the same for databases, offering additional features like data branching and vector database extensions. That said, let's try out this new integration by building a URL shortener API with Neon, Azure serverless, and Node.js. Note: You should have access to a terminal, an editor like VS Code, and Node v22 or later installed. Setting Up the Infrastructure We are going to have to do things a little backward today. Instead of writing the code, we will first first set up our serverless function and database. Step 1. Open up the Azure web portal. If you don’t already have one, you will need to create a Microsoft account. Step 2. You will also have to create a subscription if you don’t have one already, which you can do in Azure. Step 3. Now, we can create a resource group to store our serverless function and database. Go to Azure's new resource group page and fill out the form like this: This is the Azure Resource Group creation page with the resource group set to "AzureNeonURLShortener" and the location set to West US 3.In general, use the location closest to you and your users, as the location will determine the default placement of serverless functions and what areas have the lowest latency. It isn’t vital in this example, but you can search through the dropdown if you want to use another. However, note that Neon doesn’t have locations in all of these regions yet, meaning you would have to place your database in a region further from your serverless function. Step 4. Click "Review & Create" at the bottom to access a configuration review page. Then click "Create" again. Step 5. Now, we can create a serverless function. Unfortunately, it includes another form. Go to the Azure Flex consumption serverless app creation page and complete the form. Use the resource group previously created, choose a unique serverless function name, place the function in your resource group region, and use Node v20. Step 6. The name you choose for your serverless app will be the subdomain Azure gives you to access your API, so choose wisely. After you finish filling everything out, click "Review and Create" and finally, "Create." Azure should redirect you to the new app's page. Now we can set up Neon. Open the new Neon Resource page on the Azure portal, and, you guessed it, fill out the form. How to Create a Neon Database on Azure Step 1. Create a new Neon resource page with "AzureURLNeonShortener" as the resource group, "URLShortenerDB" as the resource name, and "West US 3" as the location. If the area you chose isn’t available, choose the next closest region. Once you complete everything, click "Review & Create" and then "Create," as you did for previous resources. Step 2. You might have to wait a bit for the Neon database to instantiate. Once it does, open its configuration page and click "Go To Neon." Step 3. You will be redirected to a login page. Allow Neon to access your Azure information, and then you should find yourself on a project creation page. Fill out the form below: The project and database name aren't significant, but make sure to locate the database in Azure West US 3 (or whatever region you choose). This will prevent database queries from leaving the data center, decreasing latency. Step 4. Click "Create" at the bottom of the page, keeping the default autoscaling configuration. You should now be redirected to a Neon database page. This page has our connection string, which we will need to connect to our database from our code. Click "Copy snippet" to copy the connection string. Make sure you don’t lose this, as we will need it later, but for now, we need to structure our database. Step 5. Click “SQL Editor” on the side navigation, and paste the following SQL in: SQL CREATE TABLE IF NOT EXISTS urls(id char(12) PRIMARY KEY, url TEXT NOT NULL); Then click "Run." This will create the table we will use to store URLs. The table is pretty simple: The primary key ID is a 12 — character random string that we will use to refer to URLs, and the URL is a variable-length string that will store the URL itself. Step 6. If you look at the Table view on the side navigation, you should see a “urls” table. Finally, we need to get our connection string. Click on “Dashboard” on the side nav, find the connection string, and click “Copy snippet.” Now, we can start writing code. Building the API Step 1. First, we must install Azure’s serverless CLI, which will help us create a project and eventually test/publish it. Open a terminal and run: Plain Text npm install -g azure-functions-core-tools --unsafe-perm true Step 2. If you want to use other package managers like Yarn or pnpm, just replace npm with your preferred package manager. Now, we can start on our actual project. Open the folder you want the project to be in and run the following three commands: Plain Text func init --javascript func new --name submit --template "HTTP trigger" func new --name url --template "HTTP trigger" npm install nanoid @neondatabase/serverless Now, you should see a new Azure project in that folder. The first command creates the project, the two following commands create our serverless API routes, and the final command installs the Neon serverless driver for interfacing with our database and Nano ID for generating IDs. We could use a standard Postgres driver instead of the Neon driver, but Neon’s driver uses stateless HTTP queries to reduce latency for one-off queries. Because we are running a serverless function that might only process one request and send one query, one-off query latency is important. You will want to focus on the code in src/functions, as that is where our routes are. You should see two files there: submit.js and redirect.js. submit.js submit.js will store the code we use to submit URLs. First, open submit.js and replace its code with the following: TypeScript import { app } from "@azure/functions"; import { neon } from "@neondatabase/serverless"; import { nanoid } from "nanoid"; const sql = neon("[YOUR_POSTGRES_CONNECTION_STRING]"); app.http("submit", { methods: ["GET"], authLevel: "anonymous", route: "submit", handler: async (request, context) => { if (!request.query.get("url")) return { body: "No url provided", status: 400, }; if (!URL.canParse(request.query.get("url"))) return { body: "Error parsing url", status: 400, }; const id = nanoid(12); await sql`INSERT INTO urls(id,url) VALUES (${id},${request.query.get( "url" )})`; return new Response(`Shortened url created with id ${id}`); }, }); Let’s break this down step by step. First, we import the Azure functions API, Neon serverless driver, and Nano ID. We are using ESM (ES Modules) here instead of CommonJS. We will need to make a few changes later on to support this. Next, we create the connection to our database. Replace [YOUR_POSTGRES_CONNECTION_STRING] with the string you copied from the Neon dashboard. For security reasons, you would likely want to use a service like Azure Key Vault to manage your keys in a production environment, but for now, just placing them in the script will do. Now, we are at the actual route. The first few properties define when our route handler should be triggered: We want this route to be triggered by a GET request to submit. Our handler is pretty simple. We first check if a URL has been passed through the URL query parameter (e.g., /submit?url=https://google.com), then we check whether it is a valid URL via the new URL.canParse API. Next, We generate the ID with Nano ID. Because our IDs are 12 characters long, we have to pass 12 to the Nano ID generator. Finally, we insert a new row with the new ID and URL into our database. The Neon serverless driver automatically parameterizes queries, so we don’t need to worry about malicious users passing SQL statements into the URL. redirect.js redirect.js is where our actual URL redirects will happen. Replace its code with the following: TypeScript import { app } from "@azure/functions"; import { neon } from "@neondatabase/serverless"; const sql = neon("[YOUR_POSTGRES_CONNECTION_STRING]"); app.http("redirect", { methods: ["GET"], authLevel: "anonymous", route: "{id:length(12)}", handler: async (request, context) => { const url = await sql`SELECT * FROM urls WHERE urls.id=${request.params.id}`; if (!url[0]) return new Response("No redirect found", { status: 404 }); return Response.redirect(url[0].url, 308); }, }); The first section of the script is the same as submit.js. Once again, replace it \[YOUR\_POSTGRES\_CONNECTION\_STRING\] with the string you copied from the Neon dashboard. The route is where things get more interesting. We need to accept any path that could be a redirect ID, so we use a parameter with the constraint of 12 characters long. Note that this could overlap if you ever have another 12-character route. If it does, you can rename the redirect route to start with a Z or other alphanumerically greater character to make Azure serverless load the redirect route after. Finally, we have our actual handler code. All we need to do here is query for a URL matching the given ID and redirect to it if one exists. We use the 308 status code in our redirect to tell browsers and search engines to ignore the original shortened URL. Config Files There are two more changes we need to make. First, we don’t want a /api prefix on all our functions. To remove this, open host.json, which should be in your project directory, and add the following: TypeScript "extensions": { "http": { "routePrefix": "" } } This allows your routes to operate without any prefixes. The one other thing we need to do is switch the project to ES Modules. Open package.json and insert the following at the end of the file: Plain Text "type": "module" That’s it! Testing and Deploying Now, you can try testing locally by running func start. You can navigate to http://localhost:7071/submit?url=https://example.com, then use the ID it gives you and navigate to http://localhost:7071/[YOUR_ID]. You should be redirected to example.com. Of course, we can’t just run this locally. To deploy, we need to install the Azure CLI, which you can do with one of the following commands, depending on your operating system: macOS (Homebrew) Plain Text brew install azure-cli Windows (WPM) Plain Text winget install -e --id Microsoft.AzureCLI Linux Plain Text curl -L <https://aka.ms/InstallAzureCli> | bash Now, restart the terminal, log in by running az login, and run the following in the project directory: Plain Text func azure functionapp publish [FunctionAppName] Replace [FunctionAppName] with whatever you named your function earlier. Now, you should be able to access your API at [FunctionAppName].azurewebsites.net. Conclusion You should now have a fully functional URL Shortener. You can access the code here and work on adding a front end. If you want to keep reading about Neon and Azure’s features, we recommend checking out Branching. Either way, I hope you learned something valuable from this guide.
Overview One of the key principles of writing a good data pipeline is ensuring accurate data is loaded into the target table. We have no control over the quality of the upstream data we read from, but we can have a few data quality (DQ) checks in our pipeline to ensure any bad data would be caught early on without letting it propagate downstream. DQ checks are critical in making sure the data that gets processed every day is reliable, and that downstream tables can query them safely. This will save a lot of time and resources, as we will be able to halt the data flow, giving us some time to do RCA and fix the issue rather than pass incorrect data. The biggest challenge with large data warehouses with multiple interdependent pipelines is that we would have no idea about the data issue if bad data gets introduced in one of the pipelines, and sometimes, it could take days, even before it's detected. Even though DQ check failures could cause some temporary delay in landing the data, it's much better than customers or users reporting data quality issues and then having to backfill all the impacted tables. Some of the common data quality issues that could occur are: Duplicate rows – a table at user grain (which means there can only be one row per user), having duplicates0 or null values – you expect certain critical columns not to have any null or 0 values, e.g., SSN, age, country columnsAbnormal row count – the overall row count of the table suddenly increases or drops compared to the historical valuesAbnormal metric value – a specific metric, say '# of daily user logins' suddenly spikes or drops compared to historical values Note: The operators we will be referencing below are part of the Dataswarm and Presto tech stack, which are a proprietary data pipeline building tool and an SQL query engine, respectively, developed at Facebook. Importance of Signal Tables It's a good practice to publish signal tables, which should serve as the source for downstream pipelines. These are essentially linked views that can be created on top of any table. Since they are views, they don’t take up any storage, so there is no reason not to build them. These should be created only after the DQ checks pass, and downstream pipelines should wait for these signal tables to be available rather than waiting for the source table directly, as these would have been vetted for any data anomalies. Building the Right DAG In the data lineage flow below, if bad data gets loaded into table1, then without DQ checks, they would get passed on to table2 and table3 as there is no way for pipelines2 and 3 to know of any data issues, as all they do is simply check if the table1 data has landed. But if DQ checks had been implemented, then it would fail the job/pipeline, and the table1_sigal wouldn’t have been created; thus, the downstream WaitForOperators would still be waiting, stopping the propagation of bad data. Types of DQ Failures to Enforce Hard failure. If these DQ checks fail, the job will fail and notify the oncall or table owner, so the signal table will not be created. These could potentially cause downstream pipelines to be delayed and could be an issue if they have tighter Service Level Agreements (SLAs). But for critical pipelines, this might be worth it, as sending bad data could have catastrophic ripple effects.Soft failure. If these fail, the oncall and table owner would be notified, but the job won't fail, so the signal table would still get published, and the data would get loaded and propagated downstream. For cases where the data quality loss is tolerable, this can be used. Setting Up DQ Checks We will go over some examples of how we can set up the different DQ checks and some simplified trigger logic behind each of the DQ operators. Some things to know beforehand: '<DATEID>' is a macro that will resolve to the date the Dataswarm pipeline is scheduled to run (e.g., when the job runs on Oct 1, 2020, it will resolve to ds = '2020-10-01').The output of presto_api will be an array of dictionaries, e.g., [{'ds': '2020-10-01', 'userID': 123, ‘country’: ‘US’}, {'ds': '2020-10-01', 'userID': 124, ‘country’: ‘CA’}, {...}], where each dictionary value represents the corresponding row values of the table being queried, and the key is the column name. Below would be the table representation of the data, Duplicate Rows We can simply aggregate by the key column (e.g., userID) specified by the user and check if there are any duplicate rows present by peforming a simple GROUP BY with a HAVING clause, and limiting to just 1 row. The presto_results variable should be empty ([]); if not, then there are duplicates present in the table. Python # output will be an array of dict representing reach row in the table # eg [{'ds': '2020-10-01', 'userID': 123}, {...}] presto_results = presto_api( namespace = 'namespace_name', sql = ''' SELECT useriID FROM table WHERE ds = '<DATEID>' GROUP BY 1 HAVING SUM(1) > 1 LIMIT 1 ''' ) if len(presto_results) > 0: # NOTIFY oncall/owner # JOB KILLED else: # JOB SUCCESS 0 or Null Values We can check if any of the specified columns have any invalid values by leveraging count_if presto UDF. Here, the output, if there are no invalid values, should be [{'userid_null_count': 0}]. Python presto_results = presto_api( namespace = 'namespace_name', sql = ''' SELECT COUNT_IF( userid IS NULL OR userid = 0 ) AS userid_null_count FROM table WHERE ds = '<DATEID>' ''' ) if presto_results[0]['userid_null_count'] > 0: # NOTIFY oncall/owner # JOB KILLED else: # JOB SUCCESS Abnormal Row Count To get a sense of what the normal/expected row count is for a table on a daily basis, we can do a simple 7-day average of the previous 7 days, and if today's value deviates too much from that, we can trigger the alert. The thresholds can be either: Static – a fixed upper and lower threshold that is always static. Every day, the operator checks if today’s row count is either over or below the thresholds.Dynamic – use a +x% and -x% threshold value (you can start with, say, 15%, and adjust as needed), and if today's value is greater than the 7d avg + x% or lower than the 7d avg - x%, then trigger the alert. Python dq_insert_operator = PrestoInsertOperator( input_data = {"in": "source_table"}, output_data = {"out": "dq_check_output_table"}, select = """ SELECT SUM(1) AS row_count FROM source_table WHERE ds = '<DATEID>' """, ) dq_row_check_result = presto_api( namespace = 'namespace_name', sql = ''' SELECT ds, row_count FROM dq_check_output_table WHERE ds >= '<DATEID-7>' ORDER BY 1 ''' ) # we will loop through the dq_row_check_result object, which will have 8 values # where we will find the average between DATEID-7 and DATEID-1 and compare against DATEID x = .15 # threshold prev_7d_list = dq_row_check_result[0:7] prev_7d_sum = sum([prev_data['row_count'] for prev_data in prev_7d_list]) prev_7d_avg = prev_7d_sum/7 today_value = dq_row_check_result[-1]['row_count'] upper_threshold = prev_7d_avg * (1 + x) lower_threshold = prev_7d_avg * (1 - x) if today_value > upper_threshold or today_value < lower_threshold: # NOTIFY oncall/owner # JOB KILLED else: # JOB SUCCESS So, every day, we calculate the sum of the total row count and load it into a dq_check_output_table (a temporary intermediate table that is specially used for storing DQ aggregated results). Then, we query the last 7 days and today's data from that table and store the values in an object, which we then loop through to calculate the upper and lower thresholds and check if today's value is violating either of them. Abnormal Metric Value If there are specific metrics that you want to track to see if there are any anomalies, you can set them up similarly to the above 'abnormal row count' check. Python dq_insert_operator = PrestoInsertOperator( input_data={"in": "source_table"}, output_data={"out": "dq_check_output_table"}, select=""" SELECT APPROX_DISTINCT(userid) AS distinct_user_count, SUM(cost) AS total_cost, COUNT_IF(has_login = True) AS total_logins FROM source_table WHERE ds = '<DATEID>' """, ) dq_row_check_result = presto_api( namespace='namespace_name', sql=''' SELECT ds, distinct_user_count, total_cost, total_logins FROM table WHERE ds >= '<DATEID-7>' ORDER BY 1 ''' ) Here, we calculate the distinct_user_count, total_cost, and total_logins metric and load it into a dq_check_output_table table, which we will query to find the anomalies. Takeaways You can extend this to any kind of custom checks/alerts like month-over-month value changes, year-over-year changes, etc. You can also specify GROUP BY clauses, for example, track the metric value at the interface or country level over a period of time. You can set up a DQ check tracking dashboard, especially for important metrics, to see how they have been behaving over time. In the screenshot below, you can see that there have been DQ failures for two of the dates in the past, while for other days, it has been within the predefined range. This can also be used to get a sense of how stable the upstream data quality is. They can save a lot of time as developers would be able to catch issues early on and also figure out where in the lineage the issue is occurring.Sometimes, the alerts could be false positive (FP) (alerts generated not due to bad/incorrect data, but maybe due to seasonality/new product launch, there could be a genuine volume increase or decrease). We need to ensure such edge cases are handled correctly to avoid noisy alerts. There is nothing worse than oncall being bombarded with FP alerts, so we want to be mindful of the thresholds we set and tune them as needed periodically.
When it comes to managing infrastructure in the cloud, AWS provides several powerful tools that help automate the creation and management of resources. One of the most effective ways to handle deployments is through AWS CloudFormation. It allows you to define your infrastructure in a declarative way, making it easy to automate the provisioning of AWS services, including Elastic Beanstalk, serverless applications, EC2 instances, security groups, load balancers, and more. In this guide, we'll explore how to use AWS CloudFormation to deploy infrastructure programmatically. We'll also cover how to manually deploy resources via the AWS Management Console and how to integrate services like Elastic Beanstalk, serverless functions, EC2, IAM, and other AWS resources into your automated workflow. Using AWS CloudFormation for Infrastructure as Code AWS CloudFormation allows you to define your infrastructure using code. CloudFormation provides a unified framework to automate and version your infrastructure by setting up Elastic Beanstalk, EC2 instances, VPCs, IAM roles, Lambda functions, or serverless applications. CloudFormation templates are written in YAML or JSON format, and they define the resources you need to provision. With CloudFormation, you can automate everything from simple applications to complex, multi-service environments. Key Features of CloudFormation Declarative configuration. Describe the desired state of your infrastructure, and CloudFormation ensures that the current state matches it.Resource management. Automatically provisions and manages AWS resources such as EC2 instances, RDS databases, VPCs, Lambda functions, IAM roles, and more.Declarative stack updates. If you need to modify your infrastructure, simply update the CloudFormation template, and it will adjust your resources to the new desired state. Steps to Use CloudFormation for Various AWS Deployments Elastic Beanstalk Deployment With CloudFormation 1. Write a CloudFormation Template Create a YAML or JSON CloudFormation template to define your Elastic Beanstalk application and environment. This template can include resources like EC2 instances, security groups, scaling policies, and even the Elastic Beanstalk application itself. Example of CloudFormation Template (Elastic Beanstalk): YAML yaml Resources: MyElasticBeanstalkApplication: Type: 'AWS::ElasticBeanstalk::Application' Properties: ApplicationName: "my-application" Description: "Elastic Beanstalk Application for my React and Spring Boot app" MyElasticBeanstalkEnvironment: Type: 'AWS::ElasticBeanstalk::Environment' Properties: EnvironmentName: "my-app-env" ApplicationName: !Ref MyElasticBeanstalkApplication SolutionStackName: "64bit Amazon Linux 2 v3.4.9 running Docker" OptionSettings: - Namespace: "aws:autoscaling:asg" OptionName: "MaxSize" Value: "3" - Namespace: "aws:autoscaling:asg" OptionName: "MinSize" Value: "2" - Namespace: "aws:ec2:vpc" OptionName: "VPCId" Value: "vpc-xxxxxxx" - Namespace: "aws:ec2:vpc" OptionName: "Subnets" Value: "subnet-xxxxxxx,subnet-yyyyyyy" 2. Deploy the CloudFormation Stack Use the AWS CLI or AWS Management Console to deploy the CloudFormation stack. Once deployed, CloudFormation will automatically create all the resources defined in the template. Deploy via AWS CLI: YAML bash aws cloudformation create-stack --stack-name MyElasticBeanstalkStack --template-body file://my-template.yml Serverless Deployment With AWS Lambda, API Gateway, and DynamoDB CloudFormation is also great for deploying serverless applications. With services like AWS Lambda, API Gateway, DynamoDB, and S3, you can easily manage serverless workloads. 1. Create a Serverless CloudFormation Template This template will include a Lambda function, an API Gateway for accessing the function, and a DynamoDB table. Example of CloudFormation Template (Serverless): YAML yaml Resources: MyLambdaFunction: Type: 'AWS::Lambda::Function' Properties: FunctionName: "MyServerlessFunction" Handler: "index.handler" Role: arn:aws:iam::123456789012:role/lambda-execution-role Code: S3Bucket: "my-serverless-code-bucket" S3Key: "function-code.zip" Runtime: nodejs14.x MyAPIGateway: Type: 'AWS::ApiGateway::RestApi' Properties: Name: "MyAPI" Description: "API Gateway for My Serverless Application" MyDynamoDBTable: Type: 'AWS::DynamoDB::Table' Properties: TableName: "MyTable" AttributeDefinitions: - AttributeName: "id" AttributeType: "S" KeySchema: - AttributeName: "id" KeyType: "HASH" ProvisionedThroughput: ReadCapacityUnits: 5 WriteCapacityUnits: 5 2. Deploy the Serverless Stack Deploy your serverless application using the AWS CLI or AWS Management Console. YAML bash aws cloudformation create-stack --stack-name MyServerlessStack --template-body file://serverless-template.yml VPC and EC2 Deployment CloudFormation can automate the creation of a Virtual Private Cloud (VPC), subnets, security groups, and EC2 instances for more traditional workloads. 1. CloudFormation Template for VPC and EC2 This template defines a simple EC2 instance within a VPC, with a security group allowing HTTP traffic. Example of CloudFormation Template (VPC and EC2): YAML Resources: MyVPC: Type: 'AWS::EC2::VPC' Properties: CidrBlock: "10.0.0.0/16" EnableDnsSupport: "true" EnableDnsHostnames: "true" MySecurityGroup: Type: 'AWS::EC2::SecurityGroup' Properties: GroupDescription: "Allow HTTP and SSH traffic" SecurityGroupIngress: - IpProtocol: "tcp" FromPort: "80" ToPort: "80" CidrIp: "0.0.0.0/0" - IpProtocol: "tcp" FromPort: "22" ToPort: "22" CidrIp: "0.0.0.0/0" MyEC2Instance: Type: 'AWS::EC2::Instance' Properties: InstanceType: "t2.micro" ImageId: "ami-xxxxxxxx" SecurityGroupIds: - !Ref MySecurityGroup SubnetId: !Ref MyVPC 2. Deploy the Stack YAML aws cloudformation create-stack --stack-name MyEC2Stack --template-body file://vpc-ec2-template.yml Advanced Features of CloudFormation AWS CloudFormation offers more than just simple resource provisioning. Here are some of the advanced features that make CloudFormation a powerful tool for infrastructure automation: Stack Sets. Create and manage stacks across multiple AWS accounts and regions, allowing for consistent deployment of infrastructure across your organization.Change Sets. Before applying changes to your CloudFormation stack, preview the changes with a change set to ensure the desired outcome.Outputs. Output values from CloudFormation that you can use for other stacks or applications. For example, output the URL of an API Gateway or the IP address of an EC2 instance.Parameters. Pass in parameters to customize your stack without modifying the template itself, making it reusable in different environments.Mappings. Create key-value pairs for mapping configuration values, like AWS region-specific values, instance types, or other environment-specific parameters. Using CloudFormation With AWS Services Beyond Elastic Beanstalk CloudFormation isn't just limited to Elastic Beanstalk deployments — it's a flexible tool that can be used with a variety of AWS services, including: AWS Lambda. Automate the deployment of serverless functions along with triggers like API Gateway, S3, or DynamoDB events.Amazon S3. Use CloudFormation to create S3 buckets and manage their configuration.AWS IAM. Automate IAM role and policy creation to control access to your resources.Amazon RDS. Define RDS databases (MySQL, PostgreSQL, etc.) with all associated configurations like VPC settings, subnets, and security groups.Amazon SQS, SNS. Manage queues and topics for your application architecture using CloudFormation.Amazon ECS and EKS. Automate the creation and deployment of containerized applications with services like ECS and EKS. Manually Deploying Infrastructure from the AWS Management Console While CloudFormation automates the process, sometimes manual intervention is necessary. The AWS Management Console allows you to deploy resources manually. 1. Elastic Beanstalk Application Go to the Elastic Beanstalk Console.Click Create Application, follow the steps to define the application name and platform (e.g., Docker, Node.js), and then manually configure the environment, scaling, and security options. 2. Serverless Applications (Lambda + API Gateway) Go to Lambda Console to create and deploy functions.Use API Gateway Console to create APIs for your Lambda functions. 3. EC2 Instances Manually launch EC2 instances from the EC2 Console and configure them with your chosen instance type, security groups, and key pairs. Conclusion AWS CloudFormation provides a consistent and repeatable way to manage infrastructure for Elastic Beanstalk applications, serverless architectures, and EC2-based applications. With its advanced features like Stack Sets, Change Sets, and Parameters, CloudFormation can scale to meet the needs of complex environments. For anyone managing large or dynamic AWS environments, CloudFormation is an essential tool for ensuring consistency, security, and automation across all your AWS deployments.
Keycloak is a powerful authentication and authorization solution that provides plenty of useful features, such as roles and subgroups, an advanced password policy, and single sign-on. It’s also very easy to integrate with other solutions. We’ve already shown you how to connect Keycloak to your Angular app, but there’s more you can do. For example, by integrating this technology with Cypress, you can enable the simulation of real-user login scenarios, including multi-factor authentication and social logins, ensuring that security protocols are correctly implemented and functioning as expected. Most importantly, you can also use Docker containers to provide a portable and consistent environment across different platforms (possibly with container image scanning, for increased security). This integration ensures easy deployment, scalability, and efficient dependency management, streamlining the process of securing applications and services. Additionally, Docker Compose can be used to orchestrate multiple containers, simplifying complex configurations and enhancing the overall management of Keycloak instances. This guide will show you precisely how to set all of this up. Let’s get started! Prerequisites The article is based on the contents of a GitHub repository consisting of several elements: Frontend application written in AngularKeycloak configurationE2E tests written in CypressDocker configuration for the whole stack The point of this tech stack is to allow users to work with Angular/Keycloak/Cypress locally and also in Docker containers. Keycloak Configuration We’ll start by setting up Keycloak, which is a crucial part of both configurations. The idea is to run it inside a Docker container and expose it at http://localhost:8080. Keycloak has predefined configurations, including users, realm, and client ID, so setting it up for this project requires minimum effort. Normal User Your normal user in the Keycloak panel should be configured using the following details: User: testPassword: sIjKqg73MTf9uTU Keycloak Administrator Here’s the default configuration for the admin user (of course, you probably shouldn’t use default settings for the admin account in real-world scenarios). User: adminPassword: admin Local Configuration This configuration allows you to work locally with an Angular application in dev mode along with E2E tests. It requires Keycloak to be run and available on http://localhost:8080. This is set in the Docker configuration, which is partially used here. To run the configuration locally, use the following commands in the command line. First, in the main project directory: JavaScript npm install In /e2e directory: JavaScript npm install In the main directory for frontend application development: JavaScript npm run start In /e2e directory: JavaScript npm run cy:run In the main project directory: JavaScript docker-compose up -d keycloak Docker Configuration Installing and configuring Docker is a relatively simple matter — the solution provides detailed documentation you can use if you run into any problems. In the context of our project, the Docker configuration does several key things: Running Keycloak and importing the predefined realm along with usersBuilding and exposing the Angular application on http://localhost:4200 via nginx on a separate Docker containerRunning e2e container to allow you to run tests via Cypress To run a dockerized configuration, type in the command line in the main project directory: JavaScript docker-compose up -d To run Cypress tests inside the container, use the following command: JavaScript docker container exec -ti e2e bash Then, inside the container, run: JavaScript npm run cy:run Test artifacts are connected to the host machine via volume, so test reports, screenshots, and videos will be available immediately on path /e2e/cypress/ in the following folders: reports, screenshots, and videos. Conclusion And that’s about it. As you can see, integrating Keycloak (or rather an Angular app that uses Keycloak), Docker, and Cypress is a relatively straightforward process. There are only a couple of steps you must take to get a consistent, containerized environment for easy deployment, scaling, and efficient dependency management — with the added benefit of real-user login scenario simulation thanks to Cypress for top-notch security.
Top 5 GRC Certifications for Cybersecurity Professionals
February 11, 2025 by
The Impact of Asynchronous Work on Engineering Innovation
February 11, 2025 by
Productivity and Organization Tips for Software Engineers
February 4, 2025
by
CORE
System Design of an Audio Streaming Service
February 11, 2025 by
From Zero to Scale With AWS Serverless
February 11, 2025 by
Understanding AWS Karpenter for Kubernetes Auto-Scaling
February 11, 2025
by
CORE
System Design of an Audio Streaming Service
February 11, 2025 by
From Zero to Scale With AWS Serverless
February 11, 2025 by
Understanding AWS Karpenter for Kubernetes Auto-Scaling
February 11, 2025
by
CORE
From Zero to Scale With AWS Serverless
February 11, 2025 by
Understanding AWS Karpenter for Kubernetes Auto-Scaling
February 11, 2025
by
CORE
Logfire: Uncomplicated Observability for Python Applications
February 11, 2025
by
CORE
From Zero to Scale With AWS Serverless
February 11, 2025 by
Understanding AWS Karpenter for Kubernetes Auto-Scaling
February 11, 2025
by
CORE
Logfire: Uncomplicated Observability for Python Applications
February 11, 2025
by
CORE
Chat Completion Models vs OpenAI Assistants API
February 11, 2025 by
SQL as the Backbone of Big Data and AI Powerhouses
February 11, 2025 by
Perfecting CRUD Functionality in NextJS
February 11, 2025 by