DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Cross-Pollination for Creativity Leveraging LLMs
  • Effective Prompt Engineering Principles for Generative AI Application
  • Custom Training of Large Language Models (LLMs): A Detailed Guide With Code Samples
  • Building a Production-Ready AI Agent in 2026: Beyond the Hello World Demo

Trending

  • [closed] DZone's 2025 Developer Community Survey
  • AI in Software Development: A Mirror, Not a Magic Wand
  • The Developer's Guide to Context-Aware AI: When Your Code Documentation Becomes Intelligent
  • Product-Led Software Delivery: Intelligent Platforms for DevOps at Scale
  1. DZone
  2. Data Engineering
  3. AI/ML
  4. Chat With Your Code: Conversational AI That Understands Your Codebase

Chat With Your Code: Conversational AI That Understands Your Codebase

In the ever-evolving software development landscape, interacting with your codebase conversationally can be a game-changer.

By 
Prince Bose user avatar
Prince Bose
·
Tharakarama Reddy Yernapalli Sreenivasulu user avatar
Tharakarama Reddy Yernapalli Sreenivasulu
·
Pavan Vemuri user avatar
Pavan Vemuri
DZone Core CORE ·
Aug. 14, 24 · Tutorial
Likes (8)
Comment
Save
Tweet
Share
4.9K Views

Join the DZone community and get the full member experience.

Join For Free

Imagine having a tool that understands your code and can answer your questions, provide insights, and even help debug issues — all through natural language queries. In this article, we’ll walk you through the process of creating a conversational AI that allows you to talk to your code using Chainlit, Qdrant, and OpenAI.

Benefits of Conversational AI for Codebases

  • Streamlined code review: Quickly review specific code modules and understand their context without spending time digging through the files.
  • Efficient debugging: Ask questions about potential issues in the code and get targeted responses, which helps reduce the time spent on troubleshooting.
  • Enhanced learning: New team members can learn about how different components in the code work without having to pair with existing experts in the code.
  • Improved documentation: Summarizing using AI would help generate explanations for complex code, making it easier to enhance documentation.

Now let us look at how we made that happen.

Preparing the Codebase for Interaction

The first step is to ensure the code base is ready for interaction. This can be possible by vectorizing the code and storing it in a vector DB, from which it can be efficiently reviewed.

Python
 
import openai
import yaml
import os
import uuid
from qdrant_client import QdrantClient, models

# Load configuration from config.yaml
with open("config.yaml", "r") as file:
    config = yaml.safe_load(file)

# Extract API keys and URLs from the config
qdrant_cloud_url = config["qdrant"]["url"]
qdrant_api_key = config["qdrant"]["api_key"]
openai_api_key = config["openai"]["api_key"]
code_folder_path = config["folder"]["path"]

# Initialize OpenAI API
openai.api_key = openai_api_key

# Initialize Qdrant client
client = QdrantClient(
    url=qdrant_cloud_url,
    api_key=qdrant_api_key,
)

def chunk_code(code, chunk_size=512):
    """
    Splits the code into chunks, each of a specified size.
    This helps in generating embeddings for manageable pieces of code.
    """
    lines = code.split('\n')
    for i in range(0, len(lines), chunk_size):
        yield '\n'.join(lines[i:i + chunk_size])

def vectorize_and_store_code(code, filename):
    try:
        # Chunk the code for better embedding representation
        code_chunks = list(chunk_code(code))

        # Generate embeddings for each chunk using the OpenAI API
        embeddings = []
        for chunk in code_chunks:
            response = openai.embeddings.create(
                input=[chunk],  # Input should be a list of strings
                model="text-embedding-ada-002"
            )
            
            # Access the embedding data correctly
            embedding = response.data[0].embedding
            embeddings.append(embedding)

        # Flatten embeddings if needed or store each chunk as a separate entry
        if len(embeddings) == 1:
            final_embeddings = embeddings[0]
        else:
            final_embeddings = [item for sublist in embeddings for item in sublist]
        
        # Ensure the collection exists
        try:
            client.create_collection(
                collection_name="talk_to_your_code",
                vectors_config=models.VectorParams(size=len(final_embeddings), distance=models.Distance.COSINE)
            )
        except Exception as e:
            print("Collection already exists or other error:", e)
    
        # Insert each chunk into the collection with relevant metadata
        for i, embedding in enumerate(embeddings):
            point_id = str(uuid.uuid4())
            points = [
                models.PointStruct(
                    id=point_id,
                    vector=embedding,
                    payload={
                        "filename": filename,
                        "chunk_index": i,
                        "total_chunks": len(embeddings),
                        "code_snippet": code_chunks[i]
                    }
                )
            ]
            client.upsert(collection_name="talk_to_your_code", points=points)
    
        return f"{filename}: Code vectorized and stored successfully."
    
    except Exception as e:
        return f"An error occurred with {filename}: {str(e)}"

def process_files_in_folder(folder_path):
    for filename in os.listdir(folder_path):
        if filename.endswith(".py"):
            file_path = os.path.join(folder_path, filename)
            with open(file_path, 'r', encoding='utf-8') as file:
                code = file.read()
                print(vectorize_and_store_code(code, filename))

if __name__ == "__main__":
    process_files_in_folder(code_folder_path)


Let us look at the noteworthy aspects of the above code.

  • Load your code files and chunk them into manageable pieces.
  • Chunking is a very important aspect. The chunk size should not be too small, where the function or module you want to know about is available in multiple chunks, or too big, where multiple functions or modules are squeezed into a single chunk; both scenarios will reduce the retrieval quality.
  • Used OpenAI's text-embedding-ada-002 model to generate embeddings for each chunk.
  • Processing and storing the embeddings in Qdrant for enhanced retrieval.
  • Adding metadata to the code chunks will help retrieve specific components and make the code conversation powerful.
  • For simplicity, I used a folder path where I placed a couple of code files that were used for building this conversational module. This can be enhanced to point to a GitHub URL.
  • 2 Python files, namely ragwithknowledgegraph.py and ragwithoutknowledgegraph.py, were used to generate embeddings and store them in a vector DB, over which questions can be asked via the chat interface.

Building the Conversational Interface

We will now set up a chainlit interface that takes user input, queries Qdrant, and returns contextually relevant information about your code.

Python
 
import chainlit as cl
import qdrant_client
import openai
import yaml
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain.prompts import PromptTemplate

# Load configuration from config.yaml
with open("config.yaml", "r") as file:
    config = yaml.safe_load(file)

# Extract API keys and URLs from the config
qdrant_cloud_url = config["qdrant"]["url"]
qdrant_api_key = config["qdrant"]["api_key"]
openai_api_key = config["openai"]["api_key"]

# Initialize OpenAI API
openai.api_key = openai_api_key

# Initialize OpenAI Embeddings
embeddings = OpenAIEmbeddings(model="text-embedding-ada-002", openai_api_key=openai_api_key)

# Initialize Qdrant client
client = qdrant_client.QdrantClient(
    url=qdrant_cloud_url,
    api_key=qdrant_api_key,
)

# Initialize OpenAI Chat model
chat_model = ChatOpenAI(openai_api_key=openai_api_key, model="gpt-4")

# Define a simple QA prompt template
qa_prompt_template = PromptTemplate(
    input_variables=["context", "question"],
    template="Given the following context:\n{context}\nAnswer the following question:\n{question}"
)

# Chainlit function to handle user input
@cl.on_message
async def handle_message(message: cl.message.Message):
    try:
        # Extract the actual text content from the message object
        user_input = message.content
        
        # Generate the query vector using OpenAI Embeddings
        query_vector = embeddings.embed_query(user_input)
        
        # Manually send the query to Qdrant
        response = client.search(
            collection_name="talk_to_your_code",
            query_vector=query_vector,
            limit=5
        )
        
        # Process and retrieve the relevant context (code snippets) from the Qdrant response
        context_list = []
        for point in response:
            code_snippet = point.payload.get('code_snippet', '')
            filename = point.payload.get('filename', 'Unknown')
            context_list.append(f"Filename: {filename}\nCode Snippet:\n{code_snippet}\n")
        
        context = "\n".join(context_list)
        if not context:
            context = "No matching documents found."
        
        # Generate a response using the LLM with the retrieved context
        prompt = qa_prompt_template.format(context=context, question=user_input)
        response_text = chat_model.predict(prompt)
        
        # Send the LLM's response
        await cl.Message(content=response_text).send()
        
    except Exception as e:
        # Log the error
        print(f"Error during message handling: {e}")
        await cl.Message(content=f"An error occurred: {str(e)}").send()

if __name__ == "__main__":
    cl.run()


Important aspects of the above code:

  • Initialize chainlit and configure it to interact with OpenAI and Qdrant.
  • Generate query vectors for the input to help retrieve the relevant code snippets from Qdrant.
  • Define a prompt template that combines the context retrieved from Qdrant with the user's question.
  • Make the context and question available to OpenAI's language model and return the generated answer to the user.
  • Please note that I have simplified some of the implementation for better understanding.

Output From the Chat Interface

Let us look at the output generated by the chat interface when we asked to summarize one of the code files. As mentioned earlier, we loaded the 2 Python files to vector db, and I asked to summarize one of the scripts. 

One uses a knowledge graph, and the other one does not for implementing a simple RAG use case. The LLM did a good job of summarizing the script in natural language.

LLM summary of the script in natural language

Next Steps

  • Improve retrieval by incorporating additional metadata to identify various aspects of the code.
  • Integrate the chat interface to take in a GitHub URL and ingest the code base which can be used to ask questions.
  • Test the application by asking specific and broad questions to see how well the application understands the context.
  • Engineer prompts and test retrieval using various different prompts.

Conclusion

Creating a conversational AI that understands your codebase will unlock a new level of efficiency and insight in your development process. Whether you’re streamlining code reviews, accelerating debugging, or enhancing team collaboration, this approach offers immense value. With this simple approach, you can transform the way you interact with your code.

Share your experiences and improvements with the community to help shape the future of code interaction.

AI Language model Python (language) Knowledge Graph

Opinions expressed by DZone contributors are their own.

Related

  • Cross-Pollination for Creativity Leveraging LLMs
  • Effective Prompt Engineering Principles for Generative AI Application
  • Custom Training of Large Language Models (LLMs): A Detailed Guide With Code Samples
  • Building a Production-Ready AI Agent in 2026: Beyond the Hello World Demo

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook