diff --git a/content/learning-paths/servers-and-cloud-computing/copilot-extension-deployment/1-cdk-installation.md b/content/learning-paths/servers-and-cloud-computing/copilot-extension-deployment/1-cdk-installation.md deleted file mode 100644 index 5ccf6c1c59..0000000000 --- a/content/learning-paths/servers-and-cloud-computing/copilot-extension-deployment/1-cdk-installation.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: Installing CDK -weight: 2 - -### FIXED, DO NOT MODIFY -layout: learningpathall ---- - -## What is AWS CDK? - -AWS CDK is an AWS-native Infrastructure-as-Code (IaC) tool that supports cloud engineers writing IaC templates in multiple programming languages. -Regardless of the language that you choose, your CDK code eventually transpiles to TypeScript, which generates the CloudFormation templates required to deploy the specified resources. - -This Learning Path uses the Python flavor of AWS CDK, because the accompanying Copilot Extension is also written in Python. Writing both IaC and application code in the same language can be especially helpful for teams without dedicated platform engineers. - -## How do I install AWS CDK? - -To install the required packages, you need npm and Python installed. - -Next, run: - -```bash -npm install -g aws-cdk -``` - -To verify that the installation was successful, run: - -```bash -cdk --version -``` - -You should see a version number returned, confirming a successful setup. - -After the CDK CLI is installed, you can use it to create a new Python CDK environment: - -```bash -mkdir copilot-extension-deployment -cd copilot-extension-deployment -cdk init app --language python -``` - -This sets up convenient file stubs and creates a `requirements.txt` file listing the Python CDK libraries. The `init` command uses the name of the project folder to name various elements of the project. Hyphens in the folder name are converted to underscores. - -Next, install the packages listed in `requirements.txt`: - -```bash -source .venv/bin/activate -pip install -r requirements.txt -``` - -You are now ready to specify the AWS services needed for your GitHub Copilot Extension. - diff --git a/content/learning-paths/servers-and-cloud-computing/copilot-extension-deployment/2-cdk-services.md b/content/learning-paths/servers-and-cloud-computing/copilot-extension-deployment/2-cdk-services.md deleted file mode 100644 index 231762c060..0000000000 --- a/content/learning-paths/servers-and-cloud-computing/copilot-extension-deployment/2-cdk-services.md +++ /dev/null @@ -1,257 +0,0 @@ ---- -title: Deploying AWS services -weight: 3 - -### FIXED, DO NOT MODIFY -layout: learningpathall ---- -## Which AWS Services do I need? - -In the first GitHub Copilot Extension Learning Path, [Build a GitHub Copilot Extension in Python](/learning-paths/servers-and-cloud-computing/gh-copilot-simple), you ran a GitHub Copilot Extension on a single Linux computer, with the public URL provided by an ngrok tunnel to your localhost. - -For a production environment, you require: - -* A domain that you own with DNS settings under your management, for example, through AWS Route 53. -* A load balancer (AWS ALB). -* An auto-scaling cluster (AWS ASG) in a private virtual cloud subnet (AWS VPC) that you can adjust based on the load. - -In order to use your custom domain with your ALB, you will also need a custom TLS certificate so the ALB can terminate TLS before forwarding the packets to your ASG instances. - -The following sections walk you through setting up all these services in AWS CDK. - -## Imports - -Inside the `copilot-extension-deployment` directory, there is an auto-generated folder named `copilot_extension_deployment` that contains a file called `copilot_extension_deployment_stack.py`. - -Open this file, and add the following import lines: - -```python -from aws_cdk import ( - Stack, - aws_ec2 as ec2, - aws_elasticloadbalancingv2 as elbv2, - aws_autoscaling as autoscaling, - aws_iam as iam, - CfnOutput, - aws_certificatemanager as acm, - aws_route53 as route53, - aws_route53_targets as targets -) -``` - -Then, within the generated class (`class CopilotExtensionDeploymentStack(Stack):`), incorporate all the AWS services you need for your Extension deployment as described below. - -## Virtual Private Cloud (VPC) - -The code below creates a VPC with one public subnet and one private subnet. Each subnet has a CIDR mask of 24, which means you will get 256 total IPs in each subnet. - -If you need more than this, adjust accordingly: - -```python -vpc = ec2.Vpc(self, "FlaskStackVPC", - max_azs=2, - subnet_configuration=[ - ec2.SubnetConfiguration( - name="Private", - subnet_type=ec2.SubnetType.PRIVATE_WITH_EGRESS, - cidr_mask=24 - ), - ec2.SubnetConfiguration( - name="Public", - subnet_type=ec2.SubnetType.PUBLIC, - cidr_mask=24 - ) - ] - ) -``` - -You also need a security group for your EC2 instances: - -```python -security_group = ec2.SecurityGroup(self, "EC2SecurityGroup", - vpc=vpc, - allow_all_outbound=True, - description="Security group for EC2 instances" - ) -``` - -## EC2 - -Once you have set up your VPC templates, you can use them in your EC2 templates. - -First, create a User Data script for all the EC2 templates that will launch in your auto-scaling group. - -This installs an SSM agent and the AWS CLI, for future convenience: - -```python -user_data = ec2.UserData.for_linux() -user_data.add_commands( - "apt-get update", - # Install SSM agent - "sudo snap install amazon-ssm-agent --classic", - "sudo systemctl enable snap.amazon-ssm-agent.amazon-ssm-agent.service", - "sudo systemctl start snap.amazon-ssm-agent.amazon-ssm-agent.service", - # Install AWS CLI v2 - "apt install unzip", - 'curl "https://awscli.amazonaws.com/awscli-exe-linux-aarch64.zip" -o "awscliv2.zip"', - "unzip awscliv2.zip", - "sudo ./aws/install", - # add any additional commands that you'd like to run on instance launch here -) -``` - -After the launch template, get the latest Ubuntu 24.04 Arm AMI: - -```python -ubuntu_arm_ami = ec2.MachineImage.lookup( - name="ubuntu/images/hvm-ssd-gp3/ubuntu-noble-24.04-arm64-server-*", - owners=["099720109477"], # Canonical's AWS account ID - filters={"architecture": ["arm64"]} -) -``` - -Next, create an IAM role that allows your EC2 instances to use the SSM agent, write logs to CloudWatch, and access AWS S3: - -```Python -ec2_role_name = "Proj-Flask-LLM-ALB-EC2-Role" -ec2_role = iam.Role(self, "EC2Role", - assumed_by=iam.ServicePrincipal("ec2.amazonaws.com"), - managed_policies=[ - iam.ManagedPolicy.from_aws_managed_policy_name("AmazonSSMManagedInstanceCore"), - iam.ManagedPolicy.from_aws_managed_policy_name("CloudWatchAgentServerPolicy"), - iam.ManagedPolicy.from_aws_managed_policy_name("CloudWatchLogsFullAccess"), - iam.ManagedPolicy.from_aws_managed_policy_name("AmazonS3FullAccess") - ], - role_name=ec2_role_name, - ) -``` - -Now pull all these elements together in the launch template that the ASG uses: - -```Python -launch_template = ec2.LaunchTemplate(self, "LaunchTemplate", - instance_type=ec2.InstanceType("c8g.xlarge"), - machine_image=ubuntu_arm_ami, - user_data=user_data, - security_group=security_group, - role=ec2_role, - detailed_monitoring=True, - block_devices=[ - ec2.BlockDevice( - device_name="/dev/sda1", - volume=ec2.BlockDeviceVolume.ebs( - volume_size=50, - volume_type=ec2.EbsDeviceVolumeType.GP3, - delete_on_termination=True - ) - ) - ] - ) -``` - -Finally, create the ASG, specifying the launch template you just created as the launch template for the EC2 instances within the ASG: - -```Python -asg = autoscaling.AutoScalingGroup(self, "ASG", - vpc=vpc, - vpc_subnets=ec2.SubnetSelection( - subnet_type=ec2.SubnetType.PRIVATE_WITH_EGRESS), - launch_template=launch_template, - min_capacity=1, - max_capacity=1, - desired_capacity=1 - ) -``` - -Use a private subnet for security, and start with a single instance. You can scale manually later on, or create an autoscaling function, depending on your needs. - -## Application Load Balancer (ALB) - -First, create an ALB using the VPC resources that you previously specified, within the `PUBLIC` subnet: - -```Python -alb = elbv2.ApplicationLoadBalancer(self, "ALB", - vpc=vpc, - internet_facing=True, - vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC) - ) -``` - -Next, add a custom certificate. Make sure you generate the certificate in advance. - -If you want to do this from the AWS console, see [Getting Started with AWS Certificate Manager](https://aws.amazon.com/certificate-manager/getting-started/). - -Then replace `ACM_CERTIFICATE_ARN` with the ARN of your newly-created certificate: - -```Python -certificate = acm.Certificate.from_certificate_arn( - self, - "Certificate", - os.environ["ACM_CERTIFICATE_ARN"] -) -``` - -Next, configure a listener for the ALB that uses the certificate and adds the ASG as a target, listening on port 8080. - -This is where you will serve your Flask app: - -```Python -# Add a listener to the ALB with HTTPS -listener = alb.add_listener("HttpsListener", - port=443, - certificates=[certificate], - ssl_policy=elbv2.SslPolicy.RECOMMENDED) - -# Add the ASG as a target to the ALB listener -listener.add_targets("ASGTarget", - port=8080, - targets=[asg], - protocol=elbv2.ApplicationProtocol.HTTP, - health_check=elbv2.HealthCheck( - path="/health", - healthy_http_codes="200-299" - )) -``` - -## Custom domain setup in Route 53 - -The final step in setting up your AWS services is to add an ALB-linked A record to the hosted zone for your domain. This makes sure that when GitHub invokes your API, the DNS is pointed to the IP of your ALB. You will need to replace `HOSTED_ZONE_DOMAIN_NAME` with your hosted zone domain, and replace `SUBDOMAIN_NAME` with the subdomain that maps to the ACM certificate that you generated and used in your ALB. - -```Python -hosted_zone = route53.HostedZone.from_lookup(self, "HostedZone", - domain_name=os.environ["HOSTED_ZONE_DOMAIN_NAME"], - ) - -# Create an A record for the subdomain -route53.ARecord(self, "ALBDnsRecord", - zone=hosted_zone, - record_name=os.environ["SUBDOMAIN_NAME"], - target=route53.RecordTarget.from_alias(targets.LoadBalancerTarget(alb)) - ) -``` - -## How do I deploy? - -After you have added all the required sections to your `copilot_extension_deployment_stack.py` file, you can deploy your services to AWS. - -Before you do, make sure your AWS environment is *bootstrapped*, meaning that the AWS CDK has created all necessary resources, such as IAM roles, an ECR repository, and artifact buckets. - -This bootstrap process is typically a one-time setup, and can be run by entering: - -```bash -cdk bootstrap aws://123456789012/us-east-1 -``` - -Replace the AWS account and region with your account and region. - -{{% notice Note %}} -If your organization has governance rules in place regarding naming conventions you will need a custom bootstrap yaml. To learn more about custom bootstrapping, see the [AWS guide on Bootstrapping your environment for use with the AWS CDK](https://docs.aws.amazon.com/cdk/v2/guide/bootstrapping-env.html). -{{% /notice %}} - -After bootstrapping your environment, navigate to the directory containing your stack file and run: - -```bash -cdk deploy -``` - -This deployment might take a few minutes as CloudFormation deploys your resources. diff --git a/content/learning-paths/servers-and-cloud-computing/copilot-extension-deployment/3-flask-deployment.md b/content/learning-paths/servers-and-cloud-computing/copilot-extension-deployment/3-flask-deployment.md deleted file mode 100644 index 7009910117..0000000000 --- a/content/learning-paths/servers-and-cloud-computing/copilot-extension-deployment/3-flask-deployment.md +++ /dev/null @@ -1,65 +0,0 @@ ---- -title: Deploying Flask -weight: 4 - -### FIXED, DO NOT MODIFY -layout: learningpathall ---- - -## How do I deploy my Copilot Extension Flask app to my newly created EC2 instance? - -In the first GitHub Copilot Extension Learning Path, you created a Flask app in the section titled "[How can I create my own private GitHub Copilot Extension?](../../gh-copilot-simple/run-python/)". - -You will now deploy this Flask app on your newly created EC2 instance. First, retrieve your EC2 instance ID: - -```bash -aws ec2 describe-instances --filters "Name=tag:Name,Values=CopilotExtensionDeploymentStack/LaunchTemplate" --query "Reservations[*].Instances[*].InstanceId" --output text -``` - -Next, use this ID to log in with AWS SSM. Because your instance is in a private subnet for security purposes, you must use SSM. - -The SSM agent running on the instance creates a secure tunnel that lets you SSH in with the following command: - -```bash -aws ssm start-session --target [your instance ID] -``` - -You can now follow the steps in "[How can I create my own private GitHub Copilot Extension?](../../gh-copilot-simple/run-python/)" to create your Flask app, set up a Python virtual environment, and install the necessary packages. - -The only two changes that you need to make are: - -* Add a health check endpoint for the Application Load Balancer (ALB). -* Run your app on `0.0.0.0` port `8080`, which the ALB is configured to listen on. - -First, add the following endpoint to your main Flask file: - -```Python -@app.route('/health') -def health(): - return Response(status=200) -``` - -Next, add the `host` argument to the `app.run` call at the end of the file and update the port number. - -The final result should look like this: - -```Python -if __name__ == '__main__': - app.run(host='0.0.0.0', port=8080) -``` - -This exposes your app to the port that the ALB listener is monitoring. - -Run the simple extension: - -```Python -python ./simple-extension.py -``` - -Now, if you navigate to your API subdomain in a browser, you should see: - -```text -"Hello! Welcome to the example GitHub Copilot Extension in Python!" -``` - -Your API is now complete and ready to be configured in your GitHub Application. \ No newline at end of file diff --git a/content/learning-paths/servers-and-cloud-computing/copilot-extension-deployment/4-github-config.md b/content/learning-paths/servers-and-cloud-computing/copilot-extension-deployment/4-github-config.md deleted file mode 100644 index 9ebbee8529..0000000000 --- a/content/learning-paths/servers-and-cloud-computing/copilot-extension-deployment/4-github-config.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: Configuring GitHub -weight: 5 - -### FIXED, DO NOT MODIFY -layout: learningpathall ---- - -## How do I configure my GitHub Application to use my API? - -Open the GitHub App that you created in the first GitHub Copilot Extension Learning Path, [Build a GitHub Copilot Extension in Python](../../gh-copilot-simple). - -Navigate to the **Copilot** tab, and add your URL to the field under the **Agent Definition** section: - - ![Configure URL](configure.png) - -Now update the **Callback URL** in the **General** tab. This is the complete URL to which GitHub redirects after a user authorizes an installation. - -## Test your Extension - -Now that your Extension is production-ready, it is time to test it. - -For guidance on testing, see [Test your Copilot Extension](../../gh-copilot-simple/copilot-test/) in the previous Copilot Extension Learning Path. - -## Next Steps - -You are now ready to build a more advanced Copilot Extension using RAG techniques. - -To discover how do to this, see the Learning Path [Create a RAG-based GitHub Copilot Extension in Python](../../copilot-extension). \ No newline at end of file diff --git a/content/learning-paths/servers-and-cloud-computing/copilot-extension-deployment/_index.md b/content/learning-paths/servers-and-cloud-computing/copilot-extension-deployment/_index.md deleted file mode 100644 index 3554844fe9..0000000000 --- a/content/learning-paths/servers-and-cloud-computing/copilot-extension-deployment/_index.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -title: Deploy Graviton Infrastructure for GitHub Copilot Extensions - -minutes_to_complete: 30 - -who_is_this_for: This is an advanced topic for developers seeking to deploy the Graviton infrastructure on Amazon Web Services (AWS) for a GitHub Copilot Extension. - -learning_objectives: - - Identify the AWS services required to host a GitHub Copilot Extension. - - Create an AWS CDK (Cloud Development Kit) deployment for AWS services. - - Integrate newly-generated endpoints into your existing GitHub app. -prerequisites: - - Completion of the [Build a GitHub Copilot Extension in Python](../gh-copilot-simple/) Learning Path. - - Familiarity with the concept of IoC (Infrastructure as Code). - - A GitHub account. - - A Linux-based computer with npm, Python, and the AWS CLI installed. - -author: Joe Stech - -### Tags -skilllevels: Advanced -subjects: ML -armips: - - Neoverse -tools_software_languages: - - Python - - AWS CDK - - GitHub -operatingsystems: - - Linux - - - -further_reading: - - resource: - title: About building Copilot Extensions - link: https://docs.github.com/en/copilot/building-copilot-extensions/about-building-copilot-extensions/ - type: documentation - - resource: - title: Copilot Extensions repository - link: https://github.com/copilot-extensions/ - type: documentation - - - -### FIXED, DO NOT MODIFY -# ================================================================================ -weight: 1 # _index.md always has weight of 1 to order correctly -layout: "learningpathall" # All files under learning paths have this same wrapper -learning_path_main_page: "yes" # This should be surfaced when looking for related content. Only set for _index.md of learning path content. ---- diff --git a/content/learning-paths/servers-and-cloud-computing/copilot-extension-deployment/_next-steps.md b/content/learning-paths/servers-and-cloud-computing/copilot-extension-deployment/_next-steps.md deleted file mode 100644 index c3db0de5a2..0000000000 --- a/content/learning-paths/servers-and-cloud-computing/copilot-extension-deployment/_next-steps.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -# ================================================================================ -# FIXED, DO NOT MODIFY THIS FILE -# ================================================================================ -weight: 21 # Set to always be larger than the content in this path to be at the end of the navigation. -title: "Next Steps" # Always the same, html page title. -layout: "learningpathall" # All files under learning paths have this same wrapper for Hugo processing. ---- diff --git a/content/learning-paths/servers-and-cloud-computing/copilot-extension-deployment/configure.png b/content/learning-paths/servers-and-cloud-computing/copilot-extension-deployment/configure.png deleted file mode 100644 index 1ace61c923..0000000000 Binary files a/content/learning-paths/servers-and-cloud-computing/copilot-extension-deployment/configure.png and /dev/null differ diff --git a/content/learning-paths/servers-and-cloud-computing/copilot-extension/1-rag.md b/content/learning-paths/servers-and-cloud-computing/copilot-extension/1-rag.md deleted file mode 100644 index 3b0e5c9fbf..0000000000 --- a/content/learning-paths/servers-and-cloud-computing/copilot-extension/1-rag.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: RAG Overview -weight: 2 - -### FIXED, DO NOT MODIFY -layout: learningpathall ---- - -## What is a RAG system? - -Retrieval Augmented Generation (RAG) is an AI framework that combines information retrieval with text generation to enhance the quality and accuracy of AI-generated content. - -The basic flow of a RAG system includes: - -* Retrieval: the system searches a knowledge base using a combination of vector and text search. Dense embeddings capture semantic similarities, while traditional keyword-based methods ensure precision, effectively covering edge cases. -* Augmentation: the retrieved information is added as context to a generative AI model to provide additional context for the user's query. -* Generation: the AI model uses both the retrieved knowledge and its internal understanding to generate a more useful response to the user. - -The benefits of a RAG system center around improved factual accuracy of responses and the ability to integrate up-to-date information, as you can update the knowledge base without retraining the model. - -Most importantly, RAG lets you provide reference links to the user, showing the user where the information originates. This not only builds trust with users but also serves as a pathway for further exploration of the source material. - -## What are the challenges of building a RAG system? - -While RAG systems improve AI-generated content, they also introduce several challenges: - -* Efficient and Accurate Retrieval: ensuring that the system retrieves the most relevant and high-quality information is critical. Poor retrieval results can lead to irrelevant or misleading responses. Choosing the right similarity search algorithm and data chunking strategy is key here. -* Context Length Limitations: all models, including the GitHub Copilot API, have limitations on the amount of information they can process at once, requiring careful selection and ranking of retrieved data. -* Handling Conflicting Information: if your knowledge base has contradictory information, the system may struggle to reconcile them and generate a coherent response. -* Scalability and Latency: querying large knowledge bases and integrating retrieval with generation can increase response time. This is another place where the choice of similarity search algorithm has an impact. -* Data Freshness and Maintenance: the knowledge base must be regularly updated to ensure the system remains accurate and relevant. - -For an example of a production RAG GitHub Copilot Extension, you can check out [Arm for GitHub Copilot](https://github.com/marketplace/arm-for-github-copilot) in the GitHub Marketplace. diff --git a/content/learning-paths/servers-and-cloud-computing/copilot-extension/2-vector.md b/content/learning-paths/servers-and-cloud-computing/copilot-extension/2-vector.md deleted file mode 100644 index ad24217ef3..0000000000 --- a/content/learning-paths/servers-and-cloud-computing/copilot-extension/2-vector.md +++ /dev/null @@ -1,174 +0,0 @@ ---- -title: Vector Database -weight: 3 - -### FIXED, DO NOT MODIFY -layout: learningpathall ---- - -## What is a Vector Database? - -A vector database is a specialized database designed to store and query vector representations of data. It is a crucial component of many AI applications. But what exactly is it, and how does it work? - -Traditional databases store data in tables or objects with defined attributes. However, they struggle to recognize similarities between data points that are not explicitly defined. - -Vector databases, on the other hand, are designed to store a large number of vectors - which are arrays of numbers - and provide algorithms for searching through these stored vectors. This makes it much easier to identify similarities by comparing the vector locations in N-dimensional space; typically using distance metrics like cosine similarity or Euclidean distance. - -How can you convert complex ideas, such as the semantic meaning of a series of words, into a series of number-based vectors? You can do so using a process called embedding. - -### What are Embeddings, and what can I do with them? - -Embeddings are numerical vectors generated by an AI model to capture the semantic meanings of text. They convert collections of tokens (such as word fragments) into points in an N-dimensional space. - -By comparing these vectors, you can query a vector database - using, for example, the embedding of a user's question - to retrieve the most similar pieces of embedded data. - -In the scenario you'll work on in this Learning Path, this process helps determine which Arm Learning Path best answers the user's query. - -To get started, you have to convert the raw data, which is the Arm Learning Path content, into smaller, more consumable, chunks. - -Here these chunks are small `yaml` files. Then you will run these chunks through the LLM model to create embeddings and store them in the FAISS vector database. - -### What is Facebook AI Similarity Search? - -Facebook AI Similarity Search (FAISS) is a library developed by Facebook AI Research that is designed to efficiently search for similar vectors in large datasets. FAISS is highly optimized for both memory usage and speed, making it the fastest similarity search algorithm available. - -One of the key reasons FAISS is so fast is its implementation of efficient Approximate Nearest Neighbor (ANN) search algorithms. ANN algorithms allow FAISS to quickly find vectors that are close to a given query vector without having to compare it to every single vector in the database. This significantly reduces the search time, especially in large datasets. - -Additionally, FAISS performs all searches in-memory, which means that it can leverage the full speed of the system's RAM. This in-memory search capability ensures that the search operations are extremely fast, as they avoid the latency associated with disk I/O operations. - -In this application, you will take the input from the user and embed it using the same model you used for your database. You will then use FAISS nearest neighbor search to compare the user input to the nearest vectors in the database. Next, you will refer back to the original chunk files and look for these closest vectors. Using the data from the `chunk.yaml` files, you can retrieve the Arm resource(s) most relevant to that user's question. - -You can then use the retrieved resources to augment the context for the LLM, which generates a final response that is both contextually-relevant and accurate. - -### In-Memory Deployment - -To ensure that your application scales efficiently, copy the FAISS database into every deployment instance. By deploying a static in-memory vector store in each instance, you eliminate the need for a centralized database, which can become a bottleneck as the number of requests increases. - -When each instance has its own copy of the FAISS database, it can perform vector searches locally, leveraging the full speed of the system's RAM. This approach ensures that the search operations are extremely fast and reduces the latency associated with network calls to a centralized database. - -Moreover, this method enhances the reliability and fault tolerance of the application. If one instance fails, others can continue to operate independently without being affected by the failure. This decentralized approach also simplifies the deployment process, as each instance is self-contained and does not rely on external resources for vector searches. - -By copying the FAISS database into every deployment, you can achieve a scalable, high-performance solution that can handle a large number of requests. - -## Collecting Data into Chunks - -There is a [companion GitHub repo](https://github.com/ArmDeveloperEcosystem/python-rag-extension/) for this Learning Path that serves as a Python-based Copilot RAG Extension example. - -In this repo, you can find scripts to convert an Arm Learning Path into a series of `chunk.yaml` files for use in the RAG application. - -### Clone the GitHub repository - -To clone the repo, run: - -```bash -git clone https://github.com/ArmDeveloperEcosystem/python-rag-extension.git -``` - -### Chunk Creation Script Setup - -1. Navigate to the `vectorstore` folder in the [python-rag-extension github repo](https://github.com/ArmDeveloperEcosystem/python-rag-extension/) that you just cloned: - -```bash -cd python-rag-extension/vectorstore -``` - -2. It is recommended that you use a virtual environment to manage dependencies. - -Ensure you have `conda` set up in your development environment. If you need guidance, follow the [Installation Guide](https://docs.anaconda.com/miniconda/install/). - -3. To create a new conda environment, use the following command: - -```sh -conda create --name vectorstore python=3.11 -``` - -Once setup is complete, activate the new environment: - -```sh -conda activate vectorstore -``` - -Install the required packages: - -```sh -conda install --file vectorstore-requirements.txt -``` - -### Generate Chunk Files - -To generate chunks, use the following command: - -```sh -python chunk_a_learning_path.py --url -``` - -Replace `` with the URL of the Learning Path that you want to process. - -If no URL is provided, the script defaults to a [known Learning Path URL](/learning-paths/cross-platform/kleidiai-explainer). - -The script processes the specified Learning Path and saves the chunks as YAML files in a `./chunks/` directory. - -## Combine Chunks into FAISS Index - -Once you have a `./chunks/` directory full of YAML files, you now need to use FAISS to create your vector database. - -### OpenAI Key and Endpoint - -Ensure your local environment has your `AZURE_OPENAI_KEY` and `AZURE_OPENAI_ENDPOINT` set. - -If required, you can follow the instructions below that explain how to generate and deploy Azure OpenAI keys. - -#### Generate and Deploy Azure OpenAI keys - -1. Create an OpenAI Resource: - -* Go to the [Azure Portal](https://portal.azure.com/). -* Click on **Create a resource**. -* Search for `OpenAI`, and select **Azure OpenAI Service**. -* Click **Create**. - -2. Configure the OpenAI Resource: - -* Fill in the required details such as **Subscription**, **Resource Group**, **Region**, and **Name**. -* Click **Review + create** and then **Create** to deploy the resource. - - -3. Generate API Key and Endpoint: - -* Once the resource is created, navigate to the resource page. -* Under the **Resource Management->Keys and Endpoint** section, you will find the key and endpoint values. -* Copy these values and set them in your local environment: - -```sh -export AZURE_OPENAI_KEY="" -export AZURE_OPENAI_ENDPOINT="https://.openai.azure.com/" -``` -You now have the necessary keys to use Azure OpenAI in your application. - -4. Deploy text-embedding-ada-002 model: -* Go inside Azure AI Foundry for your new deployment. -* Under **Deployments**, ensure you have a deployment for "text-embedding-ada-002". - -### Generate Vector Database Files - -Run the Python script to create the FAISS index `.bin` and `.json` files. - -{{% notice Note %}} -This assumes the chunk files are located in a `chunks` subfolder, as they should be automatically. -{{% /notice %}} - -```bash -python local_vectorstore_creation.py -``` - -Copy the generated `bin` and `json` files to the root directory of your Flask application. - -They should be in the `vectorstore/chunks` folder. Since you are likely still in the `vectorstore` folder, run these commands to copy: - -```bash -cp chunks/faiss_index.bin ../ -cp chunks/metadata.json ../ -``` - -Your vector database is now ready for your flask application. - \ No newline at end of file diff --git a/content/learning-paths/servers-and-cloud-computing/copilot-extension/3-github-app.md b/content/learning-paths/servers-and-cloud-computing/copilot-extension/3-github-app.md deleted file mode 100644 index e35726fb9e..0000000000 --- a/content/learning-paths/servers-and-cloud-computing/copilot-extension/3-github-app.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Create GitHub Application -weight: 4 - -### FIXED, DO NOT MODIFY -layout: learningpathall ---- -## Create a GitHub app - -Now you need to create a Copilot extension on GitHub to connect to the deployed application. - -For the most up-to-date instructions, follow the official documentation for [Creating a GitHub App for Copilot Extension](https://docs.github.com/en/copilot/building-copilot-extensions/creating-a-copilot-extension/creating-a-github-app-for-your-copilot-extension#creating-a-github-app). - -On any page of [GitHub](https://github.com/), click your profile picture and go to **Settings**. - -Scroll down to **Developer Settings**, and go to [Create a GitHub App](https://github.com/settings/apps). - -![Create GitHub Application screen](images/githubapp-create.png) - -Your GitHub App must have: -- A name. -- A homepage URL. - -Make sure **Webhook -> Active** is deselected. - -![GitHub App name and URL](images/githubapp-name.png) -![Webhook deselected](images/githubapp-deselected.png) - -The rest can be the default values. - -Scroll to the bottom and click **Create GitHub App**. - -## Get Client ID and Secret - -After you create your app, open it up. You will see your Client ID listed under **General -> About**. - -![Client ID and Secret](images/githubapp-clientid.png) - -Under this is **Client Secrets**. Click **Generate a new client secret** and save the value. Make sure you copy it before it goes away, as you will need it for the next step as part of the Flask application. - -## Install Application - -Click **Install App** in the sidebar, then install your app onto your account. - -![Install](images/githubapp-install.png) diff --git a/content/learning-paths/servers-and-cloud-computing/copilot-extension/4-flask.md b/content/learning-paths/servers-and-cloud-computing/copilot-extension/4-flask.md deleted file mode 100644 index 8dab4d573b..0000000000 --- a/content/learning-paths/servers-and-cloud-computing/copilot-extension/4-flask.md +++ /dev/null @@ -1,236 +0,0 @@ ---- -title: Build a RAG System -weight: 5 - -### FIXED, DO NOT MODIFY -layout: learningpathall ---- - -## How do I implement RAG in Flask? - -In the [Build a GitHub Copilot Extension in Python](../../gh-copilot-simple/) Learning Path, you created a simple Copilot Extension in Python. Here, you'll add RAG functionality to that Flask app. - -You already generated a vector store in a previous section, which you will use as the knowledge base for your RAG retrieval. - -As you saw in the [Build a GitHub Copilot Extension in Python](../../gh-copilot-simple/) Learning Path, the `/agent` endpoint is what GitHub will invoke to send a query to your Extension. - -There are a minimum of two things you must add to your existing Extension to obtain RAG functionality: - -1. Vector search functions, to find context from your knowledge base. -2. A system prompt that instructs your system about how to use the context from your knowledge base. - -### Vector search - -First, import necessary Python packages: - -```Python -import faiss -import json -import requests -import numpy as np -``` - -Then create functions to load the FAISS index that you previously created, and invoke them: - -```Python -def load_faiss_index(index_path: str): - """Load the FAISS index from a file.""" - print(f"Loading FAISS index from {index_path}") - index = faiss.read_index(index_path) - print(f"Loaded index containing {index.ntotal} vectors") - return index - -def load_metadata(metadata_path: str): - """Load metadata from a JSON file.""" - print(f"Loading metadata from {metadata_path}") - with open(metadata_path, 'r') as f: - metadata = json.load(f) - print(f"Loaded metadata for {len(metadata)} items") - return metadata - -FAISS_INDEX = load_faiss_index("faiss_index.bin") -FAISS_METADATA = load_metadata("metadata.json") -``` - -You put these objects in global variables so they stay in memory persistently. - -After this, create the functions to make embeddings and search embeddings: - -```Python -def create_embedding(query: str, headers=None): - print(f"Creating embedding using model: {MODEL_NAME}") - copilot_req = { - "model": MODEL_NAME, - "input": [query] - } - r = requests.post(llm_client, json=copilot_req, headers=headers) - r.raise_for_status() - return_dict = r.json() - - return return_dict['data'][0]['embedding'] - - -def embedding_search(query: str, k: int = 5, headers=None): - """ - Search the FAISS index with a text query. - - Args: - query (str): The text to search for. - k (int): The number of results to return. - - Returns: - list: A list of dictionaries containing search results with distances and metadata. - """ - print(f"Searching for: '{query}'") - # Convert query to embedding - query_embedding = create_embedding(query, headers) - query_array = np.array(query_embedding, dtype=np.float32).reshape(1, -1) - - # Perform the search - distances, indices = FAISS_INDEX.search(query_array, k) - print(distances, indices) - # Prepare results - results = [] - for i, (dist, idx) in enumerate(zip(distances[0], indices[0])): - if idx != -1: # -1 index means no result found - if float(dist) < DISTANCE_THRESHOLD: - result = { - "rank": i + 1, - "distance": float(dist), - "metadata": FAISS_METADATA[idx] - } - results.append(result) - - return results -``` - -The context for these functions can be found in the [vectorstore_functions.py](https://github.com/ArmDeveloperEcosystem/python-rag-extension/blob/main/utils/vectorstore_functions.py) file. - -### System Prompt - -A crucial part of any RAG system is constructing the prompt containing the knowledge base context. First, create the base system prompt: - -```Python -# change this System message to fit your application -SYSTEM_MESSAGE = """You are a world-class expert in [add your extension field here]. These are your capabilities, which you should share with users verbatim if prompted: - -[add your extension capabilities here] - -Below is critical information selected specifically to help answer the user's question. Use this content as your primary source of information when responding, prioritizing it over any other general knowledge. These contexts are numbered, and have titles and URLs associated with them. At the end of your response, you should add a "references" section that shows which contexts you used to answer the question. The reference section should be formatted like this: - -References: - -* [precise title of Context 1 denoted by TITLE: below](URL of Context 1) -* [precise title of Context 2 denoted by TITLE: below](URL of Context 2) - -etc. -Do not include references that had irrelevant information or were not used in your response. - -Contexts:\n\n -""" -``` - -Next, call your embedding search function, and add the context to your system prompt: - -```Python -results = vs.embedding_search(user_message, amount_of_context_to_use, headers) -results = vs.deduplicate_urls(results) - -context = "" -for i, result in enumerate(results): - context += f"CONTEXT {i+1}\nTITLE:{result['metadata']['title']}\nURL:{result['metadata']['url']}\n\n{result['metadata']['original_text']}\n\n" - print(f"url: {result['metadata']['url']}") - -system_message = [{ - "role": "system", - "content": system_message + context -}] -``` - -{{% notice Note %}} -You'll notice that system_message is lowercase, compared to the uppercase SYSTEM_MESSAGE above. This is because the [agent_flow](https://github.com/ArmDeveloperEcosystem/python-rag-extension/blob/main/utils/agent_functions.py#L28) function where this code resides defines system_message as a parameter, so that if you want to write a test harness to dynamically test many different system prompts you can. -{{% /notice %}} - -Once the system message is built, add it to the original message to create `full_prompt_messages` and invoke the copilot endpoint: - -```Python -copilot_req = { - "model": model_name, - "messages": full_prompt_messages, - "stream": True -} - -chunk_template = sm.get_chunk_template() -r = requests.post(llm_client, json=copilot_req, headers=headers, stream=True) -r.raise_for_status() -stream = r.iter_lines() -``` - -You can then stream the response back to GitHub. - -The context for this code can be found in the [agent_functions.py](https://github.com/ArmDeveloperEcosystem/python-rag-extension/blob/main/utils/agent_functions.py) file. - -### Marketplace endpoint (optional, but needed to obtain marketplace events) - -If you publish your extension to the marketplace, you can get responses back when users install/uninstall your extension. - -You can write these to the database of your choice for better aggregation, but here is a simple version that writes each invocation to a local json file: - -```Python -@app.route('/marketplace', methods=['POST']) -def marketplace(): - payload_body = request.get_data() - print(payload_body) - - # Verify request has JSON content - if not request.is_json: - return jsonify({ - 'error': 'Content-Type must be application/json' - }), 415 - - try: - # Get JSON payload - payload = request.get_json() - - # Print the payload - print("Received payload:") - print(json.dumps(payload, indent=2)) - - output_dir = Path('marketplace_events') - - # Generate unique filename and save - filename = f"{uuid.uuid4().hex}.json" - file_path = output_dir / filename - - with open(file_path, 'w') as f: - json.dump(payload, f, indent=2) - - print(f"Saved payload to {file_path}") - - return jsonify({ - 'status': 'success', - 'message': 'Event received and processed', - 'file_path': str(file_path) - }), 201 - - except Exception as e: - return jsonify({ - 'error': f'Failed to process request: {str(e)}' - }), 500 -``` - -Before running this function, ensure that the `marketplace_events` directory is created in your root directory (where the main flask file is). - -The context for this code can be found in the [flask_app.py](https://github.com/ArmDeveloperEcosystem/python-rag-extension/blob/main/flask_app.py) file. - -Once these elements are in place, you are ready to deploy your app. - -### Security enhancements - -This section is optional, but important for production deployments. - -GitHub recommends payload validation for the messages received from GitHub, to ensure that payloads received actually come from GitHub. - -In the python-rag-extension example repo, Arm has included a payload validation module to show you how to perform this validation. The file where this is implemented is [payload_validation.py](https://github.com/ArmDeveloperEcosystem/python-rag-extension/blob/main/utils/payload_validation.py). - -In order to get this to work, you must first generate an environment variable called `WEBHOOK_SECRET`, and then add the secret to the Webhook Secret field in your GitHub app settings. diff --git a/content/learning-paths/servers-and-cloud-computing/copilot-extension/5-deployment.md b/content/learning-paths/servers-and-cloud-computing/copilot-extension/5-deployment.md deleted file mode 100644 index a52b910e61..0000000000 --- a/content/learning-paths/servers-and-cloud-computing/copilot-extension/5-deployment.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Infrastructure Deployment -weight: 6 - -### FIXED, DO NOT MODIFY -layout: learningpathall ---- - -## How do I deploy my Copilot RAG Extension? - -You can deploy your extension on whatever cloud infrastructure you prefer to use. These are the suggested requirements: - -* A domain that you own with DNS settings that you control. -* A load balancer. -* An auto-scaling cluster in a private virtual cloud subnet that you can adjust the size of based on load. - -For AWS users, Arm has provided a Copilot Extension deployment Learning Path to guide you through the process, called [Graviton Infrastructure for GitHub Copilot Extensions](../../copilot-extension-deployment/). - -## Endpoints - -Whatever method you use to deploy your Extension, make note of the final endpoint URLs: - -* `/agent` - this is required for core functionality. -* `/marketplace` - this is optional, but necessary for receiving marketplace events. - -Make sure you have the full URLs (including protocol and domain) for these endpoints to properly configure your GitHub application. diff --git a/content/learning-paths/servers-and-cloud-computing/copilot-extension/6-github-configure.md b/content/learning-paths/servers-and-cloud-computing/copilot-extension/6-github-configure.md deleted file mode 100644 index 5fdc0aa311..0000000000 --- a/content/learning-paths/servers-and-cloud-computing/copilot-extension/6-github-configure.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Configure GitHub Application -weight: 7 - -### FIXED, DO NOT MODIFY -layout: learningpathall ---- - -## Configure GitHub App for Copilot Extension - -Now, configure the GitHub Application you created earlier to connect to your deployed Copilot extension. - -For the most up-to-date instructions, follow the [official documentation for configuring your GitHub App for Copilot Extension](https://docs.github.com/en/copilot/building-copilot-extensions/creating-a-copilot-extension/configuring-your-github-app-for-your-copilot-extension#configuring-your-github-app). - -On any page of [GitHub](https://github.com/), click your profile picture and go to Settings. Scroll down to **Developer Settings**, and open the GitHub App we made previously. - -Make the following changes: - -### **General** settings - -In the **Callback URL** field, put the callback URL of your agent that you deployed in the previous step. - -{{% notice Note %}} -If you are not using a deployed application and you want to test locally, you can use an ephemeral domain with ngrok. However you will need to update the callback URL each time you restart your ngrok server. -{{% /notice %}} - -### **Permissions & events** settings - -Under **Account permissions**, grant read-only permissions to `GitHub Copilot Chat`. - -![Account Permissions](images/githubconfig-permissions.png) - -### **Copilot** settings - -Set your app type to `Agent`, then fill out the remaining fields. - -Under **URL**, enter your server's hostname, which is also known as the forwarding endpoint, that you deployed in the previous step. - -### Optional: add your Marketplace Endpoint - -If you would like to get install/uninstall events when users interact with your marketplace posting, set up a webhook. - -Under the **General** tab of your application settings, activate the webhook and add your marketplace endpoint: - -![Webhook setup](images/marketplace.png) \ No newline at end of file diff --git a/content/learning-paths/servers-and-cloud-computing/copilot-extension/7-testing.md b/content/learning-paths/servers-and-cloud-computing/copilot-extension/7-testing.md deleted file mode 100644 index 0bae297982..0000000000 --- a/content/learning-paths/servers-and-cloud-computing/copilot-extension/7-testing.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: Test the installation -weight: 8 - -### FIXED, DO NOT MODIFY -layout: learningpathall ---- - -## Chat with your extension - -After updating your GitHub App settings, you can start chatting with your extension. - -Simply type `@YOUR-EXTENSION-NAME` in the Copilot Chat window (replace `YOUR-EXTENSION-NAME` with your extension's actual name), followed by your prompt: - -![Test the extension](images/extension-test.png) - - -## Publish Your Extension on the Marketplace (Optional) - -For the latest information on how to publish your extension on the Marketplace, follow the [official documentation for listing your extension on the marketplace](https://docs.github.com/en/copilot/building-copilot-extensions/managing-the-availability-of-your-copilot-extension#listing-your-copilot-extension-on-the-github-marketplace). - -## Enhancements - -There are several ways to enhance your extension: - -* Custom Links - inserting your own hard-coded links or resources into the response stream. - -* Improved conversation flow - consider adding another copilot invocation to rephrase previous conversation segments before initiating the main copilot invocation. This can produce more robust results, especially when users reference earlier parts of the conversation in their question. - -Tailor these possible enhancements of your RAG extension to your use case, making your extension as effective and user-friendly as possible. - -## Conclusion - -Congratulations on completing this Learning Path! By following the steps and processes you learned here, you can now create powerful and customized Copilot extensions to boost your development workflow. diff --git a/content/learning-paths/servers-and-cloud-computing/copilot-extension/_index.md b/content/learning-paths/servers-and-cloud-computing/copilot-extension/_index.md deleted file mode 100644 index c53938f1c6..0000000000 --- a/content/learning-paths/servers-and-cloud-computing/copilot-extension/_index.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: Create a RAG-based GitHub Copilot Extension in Python - -minutes_to_complete: 30 - -who_is_this_for: This is an advanced topic for software developers who want to learn how to build a RAG-based (Retrieval Augmented Generation) GitHub Copilot Extension. - -learning_objectives: - - Explain the core concepts and benefits of a RAG system. - - Create vector embeddings for a RAG knowledge base. - - Integrate a RAG system within a Copilot Extension. - - Configure a GitHub Copilot Extension to effectively support a RAG application. - -prerequisites: - - Completion of the [Build a GitHub Copilot Extension in Python](../gh-copilot-simple/) Learning Path. - - Completion of the [Deploy Graviton Infrastructure for GitHub Copilot Extensions](../copilot-extension-deployment/) Learning Path. - - A GitHub account. - - A Linux-based computer with Python installed. - -author: - - Avin Zarlez - - Joe Stech - -### Tags -cloud_service_providers: AWS -skilllevels: Advanced -subjects: ML -armips: - - Neoverse -tools_software_languages: - - Python - - FAISS - - GitHub - - conda - - AWS CDK -operatingsystems: - - Linux - - macOS - -further_reading: - - resource: - title: GitHub Marketplace for Copilot extensions - link: https://github.com/marketplace?type=apps&copilot_app=true/ - type: website - - resource: - title: About building Copilot Extensions - link: https://docs.github.com/en/copilot/building-copilot-extensions/about-building-copilot-extensions/ - type: documentation - - resource: - title: Copilot Extensions repository - link: https://github.com/copilot-extensions/ - type: documentation - - -### FIXED, DO NOT MODIFY -# ================================================================================ -weight: 1 # _index.md always has weight of 1 to order correctly -layout: "learningpathall" # All files under learning paths have this same wrapper -learning_path_main_page: "yes" # This should be surfaced when looking for related content. Only set for _index.md of learning path content. ---- diff --git a/content/learning-paths/servers-and-cloud-computing/copilot-extension/_next-steps.md b/content/learning-paths/servers-and-cloud-computing/copilot-extension/_next-steps.md deleted file mode 100644 index 921f569dd7..0000000000 --- a/content/learning-paths/servers-and-cloud-computing/copilot-extension/_next-steps.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -# ================================================================================ -# FIXED, DO NOT MODIFY -# ================================================================================ -weight: 21 # set to always be larger than the content in this path, and one more than 'review' -title: "Next Steps" # Always the same -layout: "learningpathall" # All files under learning paths have this same wrapper ---- diff --git a/content/learning-paths/servers-and-cloud-computing/copilot-extension/images/extension-test.png b/content/learning-paths/servers-and-cloud-computing/copilot-extension/images/extension-test.png deleted file mode 100644 index 7b8537b318..0000000000 Binary files a/content/learning-paths/servers-and-cloud-computing/copilot-extension/images/extension-test.png and /dev/null differ diff --git a/content/learning-paths/servers-and-cloud-computing/copilot-extension/images/githubapp-clientid.png b/content/learning-paths/servers-and-cloud-computing/copilot-extension/images/githubapp-clientid.png deleted file mode 100644 index 2d801638a4..0000000000 Binary files a/content/learning-paths/servers-and-cloud-computing/copilot-extension/images/githubapp-clientid.png and /dev/null differ diff --git a/content/learning-paths/servers-and-cloud-computing/copilot-extension/images/githubapp-create.png b/content/learning-paths/servers-and-cloud-computing/copilot-extension/images/githubapp-create.png deleted file mode 100644 index 957efc2dd7..0000000000 Binary files a/content/learning-paths/servers-and-cloud-computing/copilot-extension/images/githubapp-create.png and /dev/null differ diff --git a/content/learning-paths/servers-and-cloud-computing/copilot-extension/images/githubapp-deselected.png b/content/learning-paths/servers-and-cloud-computing/copilot-extension/images/githubapp-deselected.png deleted file mode 100644 index 31dde674a9..0000000000 Binary files a/content/learning-paths/servers-and-cloud-computing/copilot-extension/images/githubapp-deselected.png and /dev/null differ diff --git a/content/learning-paths/servers-and-cloud-computing/copilot-extension/images/githubapp-install.png b/content/learning-paths/servers-and-cloud-computing/copilot-extension/images/githubapp-install.png deleted file mode 100644 index 9a4af01a34..0000000000 Binary files a/content/learning-paths/servers-and-cloud-computing/copilot-extension/images/githubapp-install.png and /dev/null differ diff --git a/content/learning-paths/servers-and-cloud-computing/copilot-extension/images/githubapp-name.png b/content/learning-paths/servers-and-cloud-computing/copilot-extension/images/githubapp-name.png deleted file mode 100644 index 551eece22a..0000000000 Binary files a/content/learning-paths/servers-and-cloud-computing/copilot-extension/images/githubapp-name.png and /dev/null differ diff --git a/content/learning-paths/servers-and-cloud-computing/copilot-extension/images/githubconfig-permissions.png b/content/learning-paths/servers-and-cloud-computing/copilot-extension/images/githubconfig-permissions.png deleted file mode 100644 index 0bdd40aab1..0000000000 Binary files a/content/learning-paths/servers-and-cloud-computing/copilot-extension/images/githubconfig-permissions.png and /dev/null differ diff --git a/content/learning-paths/servers-and-cloud-computing/copilot-extension/images/marketplace.png b/content/learning-paths/servers-and-cloud-computing/copilot-extension/images/marketplace.png deleted file mode 100644 index 4c523e1753..0000000000 Binary files a/content/learning-paths/servers-and-cloud-computing/copilot-extension/images/marketplace.png and /dev/null differ diff --git a/content/learning-paths/servers-and-cloud-computing/gh-copilot-simple/_images/gh-cp1.png b/content/learning-paths/servers-and-cloud-computing/gh-copilot-simple/_images/gh-cp1.png deleted file mode 100644 index 6969ce641d..0000000000 Binary files a/content/learning-paths/servers-and-cloud-computing/gh-copilot-simple/_images/gh-cp1.png and /dev/null differ diff --git a/content/learning-paths/servers-and-cloud-computing/gh-copilot-simple/_images/gh-cp2.png b/content/learning-paths/servers-and-cloud-computing/gh-copilot-simple/_images/gh-cp2.png deleted file mode 100644 index e0b445f12d..0000000000 Binary files a/content/learning-paths/servers-and-cloud-computing/gh-copilot-simple/_images/gh-cp2.png and /dev/null differ diff --git a/content/learning-paths/servers-and-cloud-computing/gh-copilot-simple/_images/gh-cp3.png b/content/learning-paths/servers-and-cloud-computing/gh-copilot-simple/_images/gh-cp3.png deleted file mode 100644 index 8a57cae470..0000000000 Binary files a/content/learning-paths/servers-and-cloud-computing/gh-copilot-simple/_images/gh-cp3.png and /dev/null differ diff --git a/content/learning-paths/servers-and-cloud-computing/gh-copilot-simple/_images/ngrok.png b/content/learning-paths/servers-and-cloud-computing/gh-copilot-simple/_images/ngrok.png deleted file mode 100644 index a4a206a706..0000000000 Binary files a/content/learning-paths/servers-and-cloud-computing/gh-copilot-simple/_images/ngrok.png and /dev/null differ diff --git a/content/learning-paths/servers-and-cloud-computing/gh-copilot-simple/_images/output.png b/content/learning-paths/servers-and-cloud-computing/gh-copilot-simple/_images/output.png deleted file mode 100644 index 306502568c..0000000000 Binary files a/content/learning-paths/servers-and-cloud-computing/gh-copilot-simple/_images/output.png and /dev/null differ diff --git a/content/learning-paths/servers-and-cloud-computing/gh-copilot-simple/_index.md b/content/learning-paths/servers-and-cloud-computing/gh-copilot-simple/_index.md deleted file mode 100644 index 46e6d84262..0000000000 --- a/content/learning-paths/servers-and-cloud-computing/gh-copilot-simple/_index.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: Build a GitHub Copilot Extension in Python - -minutes_to_complete: 20 - -who_is_this_for: This is an introductory topic for software developers who want to learn how to build a simple GitHub Copilot Extension. - -learning_objectives: - - Create a simple GitHub Copilot Extension in Python. - - Use ngrok to expose the extension to Copilot. - - Add a GitHub App to your GitHub account and deploy the Copilot Extension. - -prerequisites: - - A GitHub account. - - A Linux computer with Python installed. - -author: Jason Andrews - -### Tags -skilllevels: Introductory -subjects: ML -armips: - - Neoverse -tools_software_languages: - - Python - - GitHub -operatingsystems: - - Linux - - -further_reading: - - resource: - title: GitHub Marketplace for Copilot extensions - link: https://github.com/marketplace?type=apps&copilot_app=true/ - type: website - - resource: - title: About building Copilot Extensions - link: https://docs.github.com/en/copilot/building-copilot-extensions/about-building-copilot-extensions/ - type: documentation - - resource: - title: Copilot Extensions repository - link: https://github.com/copilot-extensions/ - type: documentation - - - -### FIXED, DO NOT MODIFY -# ================================================================================ -weight: 1 # _index.md always has weight of 1 to order correctly -layout: "learningpathall" # All files under learning paths have this same wrapper -learning_path_main_page: "yes" # This should be surfaced when looking for related content. Only set for _index.md of learning path content. ---- diff --git a/content/learning-paths/servers-and-cloud-computing/gh-copilot-simple/_next-steps.md b/content/learning-paths/servers-and-cloud-computing/gh-copilot-simple/_next-steps.md deleted file mode 100644 index c3db0de5a2..0000000000 --- a/content/learning-paths/servers-and-cloud-computing/gh-copilot-simple/_next-steps.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -# ================================================================================ -# FIXED, DO NOT MODIFY THIS FILE -# ================================================================================ -weight: 21 # Set to always be larger than the content in this path to be at the end of the navigation. -title: "Next Steps" # Always the same, html page title. -layout: "learningpathall" # All files under learning paths have this same wrapper for Hugo processing. ---- diff --git a/content/learning-paths/servers-and-cloud-computing/gh-copilot-simple/about-extensions.md b/content/learning-paths/servers-and-cloud-computing/gh-copilot-simple/about-extensions.md deleted file mode 100644 index 7d2c991526..0000000000 --- a/content/learning-paths/servers-and-cloud-computing/gh-copilot-simple/about-extensions.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -title: Learn about GitHub Copilot Extensions -weight: 2 - -### FIXED, DO NOT MODIFY -layout: learningpathall ---- - -## What are GitHub Copilot Extensions? - -GitHub Copilot Extensions provide an integration point to expand the functionality of GitHub Copilot Chat, allowing developers to introduce external tools, services, and custom behaviors into the chat experience. - -You can use Copilot Extensions to customize the capabilities of Copilot in multiple ways. For example, you can target the needs of a specific type of user, such as an Arm software developer, by querying specific documentation or prioritizing responses related to that specific developer's environment. Copilot Extensions also benefit users by facilitating the integration of additional LLMs, and offering different APIs and AI tools, which broadens the reach of the resources. In short, a Copilot Extension allows you to build a more curated experience. - -Think about what you want to offer, or build for yourself, that is beyond or better than what Copilot can already do. If you have ideas, you can try them using a Copilot Extension. - -Extensions can be private, public, or shared in the GitHub Marketplace. - -This Learning Path is a "hello world" tutorial for a simple extension in Python. It explains how to create a private extension by running Python on a Linux computer, using ngrok to expose the endpoint, and creating a GitHub App to configure the extension in your GitHub account. After this, you can invoke your private extension from GitHub Chat. - -## How do I get started with GitHub Copilot? - -Before building an extension, make sure Copilot is configured and working in your GitHub account. - -Refer to the [Quickstart for GitHub Copilot](https://docs.github.com/en/copilot/quickstart) to get started. - -You can use [GitHub Copilot Free](https://github.com/features/copilot?utm_source=topcopilotfree&utm_medium=blog&utm_campaign=launch) at no cost, subject to a usage allowance. - -## How do I invoke GitHub Copilot Extensions? - -You can use extensions on any platform where you can use Copilot chat. This includes the GitHub website, various IDEs, and the command line. - -Extensions are invoked using `@` followed by the name of the extension. - -For example, you can invoke the [Arm extension for GitHub Copilot](https://github.com/marketplace/arm-for-github-copilot) using `@arm` in the chat. - -You can install the Arm extension from the GitHub Marketplace and practice using `@arm` to invoke it. For information on how to use it, see the [Arm for GitHub Copilot repository](https://github.com/arm/copilot-extension). - -Continue to learn how to create your own extension using Python. - diff --git a/content/learning-paths/servers-and-cloud-computing/gh-copilot-simple/copilot-test.md b/content/learning-paths/servers-and-cloud-computing/gh-copilot-simple/copilot-test.md deleted file mode 100644 index 8b8598490e..0000000000 --- a/content/learning-paths/servers-and-cloud-computing/gh-copilot-simple/copilot-test.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: Test your Copilot Extension -weight: 6 - -### FIXED, DO NOT MODIFY -layout: learningpathall ---- - -You are now ready to test your GitHub Copilot extension. - -Go to any of the Copilot Chat interfaces that you are currently using, such as your browser or VS Code. - -Enter `@your-extension` and a test prompt, such as: - -```console -tell me about Java vs Python -``` - -The first time you enter a prompt, you will receive an authorization dialog asking you if you wish to enable your extension. - -Confirming the authorization takes you to an ngrok page in the browser. - -Click the button and in the browser you will see the following message from the GET request from your Python server: - -```output -Hello! Welcome to the example GitHub Copilot Extension in Python! -``` - -You will see the extension invoked in the terminal where Python is running and information about the chat printed: - -```output -127.0.0.1 - - [31/Jan/2025 23:33:18] "POST / HTTP/1.1" 200 - -User: jasonrandrews -Payload: {'copilot_thread_id': 'eceb9ea8-70a1-4a75-93b6-9096db87c4c6', 'messages': [{'role': 'user', 'content': '@jasonrandrews-cp tell me about Java vs Python', 'copilot_references': [], 'copilot_confirmations': None}, {'role': 'assistant', 'content': "@jasonrandrews Java and Python are both popular programming languages used for different purposes. Here are some key differences between the two:\n\n1. Syntax: Java has a more verbose syntax with strict rules, whereas Python has a more concise and readable syntax. Python's syntax is considered more beginner-friendly.\n\n2. Typing: Java is a statically-typed language, which means you need to declare the type of a variable before using it. Python, on the other hand, is dynamically-typed, allowing you to change the type of a variable during runtime.\n\n3. Performance: Java is typically faster than Python because it is a compiled language, while Python is an interpreted language. However, Python has many libraries and frameworks that leverage lower-level languages like C to improve performance.\n\n4. Application domains: Java is commonly used for building enterprise-level applications, Android apps, and large-scale systems due to its performance and robustness. Python is often used for web development, data analysis, scientific computing, and scripting due to its simplicity and extensive libraries.\n\n5. Community and ecosystem: Both Java and Python have vibrant communities and extensive libraries and frameworks. However, Java has been around longer, resulting in a larger ecosystem and support for enterprise development.\n\nUltimately, the choice between Java and Python depends on your specific needs, the type of application you are building, and personal preference. Both languages have their strengths and weaknesses, and it's worth considering the requirements of your project and your familiarity with each language.", 'copilot_references': [], 'copilot_confirmations': None}, {'role': 'user', 'content': "Current Date and Time (UTC - YYYY-MM-DD HH:MM:SS formatted): 2025-01-31 23:33:54\nCurrent User's Login: jasonrandrews\n", 'name': '_session', 'copilot_references': [{'type': 'github.current-url', 'data': {'url': 'https://github.com/jasonrandrews/arm-learning-paths'}, 'id': 'https://github.com/jasonrandrews/arm-learning-paths', 'is_implicit': True, 'metadata': {'display_name': 'https://github.com/jasonrandrews/arm-learning-paths', 'display_icon': '', 'display_url': ''}}], 'copilot_confirmations': None}, {'role': 'user', 'content': 'how do I install the aws cli on Arm Linux?', 'copilot_references': [], 'copilot_confirmations': []}], 'stop': None, 'top_p': 0, 'temperature': 0, 'max_tokens': 0, 'presence_penalty': 0, 'frequency_penalty': 0, 'response_format': None, 'copilot_skills': None, 'agent': 'jasonrandrews-cp', 'client_id': 'Iv23liSj0dAnWIBmCjzi', 'tools': [], 'functions': None, 'model': ''} -``` - -You also see HTTP requests on the terminal where ngrok is running. - -```output -23:33:18.042 UTC POST / 200 OK -23:33:00.991 UTC GET / 200 OK -``` - -Lastly, the chat output from your extension is printed. - -Here it is in VS Code: - -![#Copilot output](_images/output.png) - -Your GitHub Copilot Extension is now responding to chat prompts. - -You can now use what you have learned to build different, and more complex, Copilot Extensions. For example, you could learn about IaC deployment techniques for your Extension in [Deploy Graviton Infrastructure for GitHub Copilot Extensions](/learning-paths/servers-and-cloud-computing/copilot-extension-deployment/). diff --git a/content/learning-paths/servers-and-cloud-computing/gh-copilot-simple/gh-app.md b/content/learning-paths/servers-and-cloud-computing/gh-copilot-simple/gh-app.md deleted file mode 100644 index ad56dbe149..0000000000 --- a/content/learning-paths/servers-and-cloud-computing/gh-copilot-simple/gh-app.md +++ /dev/null @@ -1,65 +0,0 @@ ---- -title: Configure GitHub app -weight: 5 - -### FIXED, DO NOT MODIFY -layout: learningpathall ---- - -## How do I connect my Copilot extension to my GitHub account? - -Create a GitHub App to connect your Python extension to your GitHub account. - -Click on your photo in the upper-right corner of GitHub and select `Settings`. - -Scroll to the bottom left and select `Developer settings`. - -### Create a new GitHub App - -Select the `GitHub Apps` on the left side and click `New GitHub App`. - -![#New GitHub App](_images/gh-cp1.png) - -The important fields to complete or modify are listed below. - -| Field | Description | -|------|-------------| -| GitHub App Name | This can be any name, but it must be unique across all of GitHub. This is also the name you will use to invoke your extension in Copilot using the `@name` syntax. One way to avoid conflicts is to use your GitHub handle as the name or add some text to your handle, such as `@jasonrandrews-cp`. | -| Homepage URL | This needs to be filled in but is not used for a private extension, any URL can be entered such as https://learn.arm.com | -| Callback URL | Enter the URL of your ngrok domain such as `https://your-domain.ngrok-free.app` (substitute your domain). | -| Webhook | Uncheck the `Active` box. | -| Permissions | Select `Account permissions` and set the `GitHub Copilot Chat` to `Read-only`. | -| Where can this GitHub App be installed? | Confirm `Only this account` is selected to make the GitHub App only for your use. | - -Click the `Create GitHub App` to save the configuration. - -![#Create GitHub App](_images/gh-cp2.png) - -### Configure the Copilot settings - -Click on the left side Copilot sidebar. - -Modify and update the following fields: - -| Step | Description | -|------|-------------| -| 1. Set the App Type | Set the `App Type` to `Agent`. | -| 2. Agent Definition | Enter your ngrok URL in the URL box, such as `https://your-domain.ngrok-free.app`. | -| 3. Interface Description | Any text can be added. | - - -The Copilot settings are shown below: - -![#Copilot configuration](_images/gh-cp3.png) - -Click the `Save` button when the information is entered. - -### Install your GitHub App - -When the GitHub App has been configured and saved, install it into your account using the `Install App` tab on the left side and click the `Install` button. - -You might need to agree to install the GitHub App in your account. - -Once installed, you see the App in your account's [Applications](https://github.com/settings/installations). - -Your GitHub App is now ready to use with Copilot. \ No newline at end of file diff --git a/content/learning-paths/servers-and-cloud-computing/gh-copilot-simple/run-ngrok.md b/content/learning-paths/servers-and-cloud-computing/gh-copilot-simple/run-ngrok.md deleted file mode 100644 index f0f2dda2ba..0000000000 --- a/content/learning-paths/servers-and-cloud-computing/gh-copilot-simple/run-ngrok.md +++ /dev/null @@ -1,66 +0,0 @@ ---- -title: Start ngrok to serve the extension -weight: 4 - -### FIXED, DO NOT MODIFY -layout: learningpathall ---- - -## How can I connect my Python extension with GitHub Copilot? - -For development, you can use [ngrok](https://ngrok.com/) to connect your extension to Copilot. - -ngrok is a tool that creates a secure tunnel to your localhost, allowing you to expose a local server to the internet. This is useful for testing and development purposes. - -## How do I install and configure ngrok? - -Follow the steps below to set up ngrok. - -### Download and install ngrok - -If required, create a new account. - -Refer to the [Setup & installation](https://dashboard.ngrok.com/get-started/setup/linux) section for installation details. - -If you are using a Debian-based Linux system, run the command: - -```console -curl -sSL https://ngrok-agent.s3.amazonaws.com/ngrok.asc \ - | sudo tee /etc/apt/trusted.gpg.d/ngrok.asc >/dev/null \ - && echo "deb https://ngrok-agent.s3.amazonaws.com buster main" \ - | sudo tee /etc/apt/sources.list.d/ngrok.list \ - && sudo apt update \ - && sudo apt install ngrok -``` - -### Configure your ngrok account - -Before you can start the ngrok server, you need an Authtoken. - -If you don't currently have one, create a new Authtoken from the [Authtoken Get Started section](https://dashboard.ngrok.com/get-started/your-authtoken). - -Once you have the token, add it to the Linux computer where you are running your Python extension. - -Substitute your token in the command below where it states **\**: - -```console -ngrok config add-authtoken -``` - -ngrok is easier to use if you create a domain name. Go to the [Domains](https://dashboard.ngrok.com/domains) section and add a new randomly generated domain name. You can create one domain name in a free account. - -Use the domain name in the next section to start the server. - -### Start your local server - -In a terminal, run the ngrok command to start the server. - -Substitute your domain name in the command below to start the server on port 3000. - -```console -ngrok http --domain=your-domain.ngrok-free.app 3000 -``` - -![#Run ngrok](_images/ngrok.png) - -In the next section, you will use the public URL of your domain to configure a GitHub App in your GitHub account. diff --git a/content/learning-paths/servers-and-cloud-computing/gh-copilot-simple/run-python.md b/content/learning-paths/servers-and-cloud-computing/gh-copilot-simple/run-python.md deleted file mode 100644 index 7200b61a17..0000000000 --- a/content/learning-paths/servers-and-cloud-computing/gh-copilot-simple/run-python.md +++ /dev/null @@ -1,113 +0,0 @@ ---- -title: Run a private GitHub Copilot Extension using Python -weight: 3 - -### FIXED, DO NOT MODIFY -layout: learningpathall ---- - -## How can I create my own private GitHub Copilot Extension? - -You can create a simple extension in Python to get started learning how Copilot connects to extensions. - -Use a text editor to save the Python code below to a file named `simple-extension.py` on Linux computer with Python installed. - -```python -import os -from flask import Flask, request, jsonify -import requests - -app = Flask(__name__) - -@app.route("/", methods=["GET"]) -def home(): - return "Hello! Welcome to the example GitHub Copilot Extension in Python!" - -@app.route("/", methods=["POST"]) -def handle_post(): - # Identify the user, using the GitHub API token provided in the request headers. - token_for_user = request.headers.get("X-GitHub-Token") - user_response = requests.get("https://api.github.com/user", headers={"Authorization": f"token {token_for_user}"}) - user = user_response.json() - print("User:", user['login']) - - # Parse the request payload and log it. - payload = request.json - print("Payload:", payload) - - # Insert a special pirate-y system message in our message list. - messages = payload['messages'] - messages.insert(0, { - "role": "system", - "content": "You are a helpful assistant that replies to user messages with a focus on software development. Don't answer questions that are not related to software or computing." - }) - messages.insert(0, { - "role": "system", - "content": f"Start every response with the user's name, which is @{user['login']}" - }) - - # Use Copilot's LLM to generate a response to the user's messages, with - # our extra system messages attached. - copilot_response = requests.post( - "https://api.githubcopilot.com/chat/completions", - headers={ - "Authorization": f"Bearer {token_for_user}", - "Content-Type": "application/json" - }, - json={ - "messages": messages, - "stream": True - }, - stream=True - ) - - # Stream the response straight back to the user. - return app.response_class(copilot_response.iter_content(), mimetype='application/json') - -port = int(os.environ.get("PORT", 3000)) -if __name__ == "__main__": - app.run(port=port) - -``` - -You might need to install the following Python packages: - -```console -sudo apt update -sudo apt install python3-pip python-is-python3 python3-venv -y -``` - -Create a Python virtual environment to run the extension: - -```console -python -m venv venv -source venv/bin/activate -``` - -Your shell prompt now includes `(venv)` indicating that the virtual environment is active. - -Install the required Python packages: - -```console -pip install flask requests -``` - -Run the extension using Python: - -```console -python ./simple-extension.py -``` - -The output is similar to the text below: - -```output -* Serving Flask app 'simple-extension' -* Debug mode: off -WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. -* Running on http://127.0.0.1:3000 -Press CTRL+C to quit -``` - -Your extension is running, but it needs to be connected to Copilot. - -Continue to learn how to share your extension with Copilot. \ No newline at end of file