Everything changes on August 12th

Aug 5, 2025

Abid Ali Awan imageAbid Ali Awan

Building AI Applications with Kimi K2: A Complete Travel Deal Finder Tutorial

Building AI Applications with Kimi K2: A Complete Travel Deal Finder Tutorial image

Building AI Applications with Kimi K2

Build and deploy a Travel Deal application using the Groq Cloud, Firecrawl API, and the Hugging Face ecosystem.

Kimi K2 is a state-of-the-art open-source agentic AI model that is rapidly gaining attention across the tech industry. Developed by Moonshot AI, a fast-growing Chinese company, Kimi K2 delivers performance on par with leading proprietary models like Claude 4 Sonnet, but with the flexibility and accessibility of open-source models. Thanks to its advanced architecture and efficient training, developers are increasingly choosing Kimi K2 as a cost-effective and powerful alternative for building intelligent applications. In this tutorial, we will learn how Kimi K2 works, including its architecture and performance. We will guide you through selecting the best Kimi K2 model provider, then show you how to build a Travel Deal Finder application using Kimi K2 and the Firecrawl API. Finally, we will create a user-friendly interface and deploy the application on Hugging Face Spaces, making it accessible to users worldwide.

What is Kimi K2?

Kimi K2 is an open-source Large Language Model (LLM) designed for agentic AI tasks. It’s built on a mixture-of-experts (MoE) architecture featuring an impressive total of 1 trillion parameters, activating 32 billion during inference.

This model is trained on 15.5 trillion tokens using the innovative MuonClip optimizer, which effectively addresses training instabilities at this unprecedented scale, leading to robust and stable learning. Designed specifically for agentic intelligence, Kimi K2 excels in knowledge, reasoning, and coding. It’s also highly optimized for autonomous tool use and complex multi-step problem-solving. Kimi K2 features a context window of 128K tokens, advanced attention mechanisms, and strong capabilities for tool-calling. It has achieved impressive state-of-the-art results across a variety of benchmarks, including a 65.8% pass rate on the first attempt in the SWE-bench Verified coding assessments, along with exceptional performance in math, STEM, and tool-use tasks.

Image from moonshotai/Kimi-K2-Instruct · Hugging Face

Getting Started with Kimi K2 API

Kimi K2 is an open-source model, which means you can run it locally for free. However, the catch is that you need at least 32 H100 GPUs. So, what are your other options? You can choose to use the official API provided by Moonshot AI or other model providers that provide lower cost and better performance. In this section, we will cover the best methods to access the paid and free APIs for using the Kimi K2 model.

1. Groq Cloud

It’s safe to say that Groq API is the best currently available. It provides the fastest token generation and is easy to set up. At the moment, it offers free but limited access to the Kimi K2 model.

Screenshot from GroqDocs

2. Moonshot AI

Moonshot AI provides access to the models with the official API.

They don’t provide free access, meaning you need to add a credit card and add at least $10 credit to start using the Kimi K2 model.

Screenshot from Moonshot AI

3. OpenRouter

For other options to run Kimi K2, OpenRouter is the best place to explore. It’s a marketplace for all LLM APIs. You can easily find free APIs, affordable options, and those that are stable and provide fast inference. In the screenshot below, you will see that Moonshot AI is the cheapest option, but also the slowest. In contrast, Groq is a bit more expensive but provides 26 times more inference speed than Moonshot AI. Notice that while Groq offers free usage on their direct platform, OpenRouter charges for the convenience and its additional features.

Screenshot from OpenRouter

Getting Started with Groq

For this tutorial, we will use Groq as the AI model provider. First, let’s install the Groq Python SDK:

pip install groq==0.30.0

On Groq’s website, create an account to generate the Groq API key. Save the API key and set it as an environment variable:

export GROQ_API_KEY=your_groq_api_key

Then, in Python, use the Groq Python library to create a client and generate response:

import os
from groq import Groq

# initialize clients
groq_client = Groq(api_key=os.environ["GROQ_API_KEY"])


chat_completion = groq_client.chat.completions.create(
    messages=[
        {
            "role": "user",
            "content": "What is Firecrawl famous for?",
        }
    ],
    model="moonshotai/kimi-k2-instruct",
)

print(chat_completion.choices[0].message.content)

This should return a quick and accurate response from Kimi K2.

Firecrawl is best known for its ability to **turn entire websites into clean, LLM-ready markdown or structured data** in a single API call. It's become popular among developers and AI teams who need to feed web content into large-language-model pipelines, RAG systems, or fine-tuning workflows without having to write custom scrapers or crawl logic.

Building a Travel Deal Finder AI Application with Kimi K2 and Firecrawl

Now that we have Groq as an AI model provider, the next step is to build the backbone of the application using the Firecrawl API and the Kimi K2 model. We’ll write a function that combines Firecrawl’s web searching with Kimi K2’s reasoning to return the best travel deals.

1. Setting up

First, we need to obtain the API keys for Groq and Firecrawl. Currently, both platforms provide free, but limited access to their API servers, which is sufficient for testing.

export FIRECRAWL_API_KEY=your_firecrawl_api_key
export GROQ_API_KEY=your_groq_api_key

Next, install the Groq, Firecrawl, and Gradio Python packages. We will use Gradio later to build a user interface for the application, which requires Python 3.10 or higher.

pip install groq==0.30.0
pip install firecrawl-py==2.16.1
pip install gradio==5.38.0

Then, in python, initialize the clients for Groq and Firecrawl.

import os

from firecrawl import FirecrawlApp
from groq import Groq

# initialize clients
groq_client = Groq(api_key=os.environ["GROQ_API_KEY"])
firecrawl_client = FirecrawlApp(api_key=os.environ["FIRECRAWL_API_KEY"])

2. Testing Firecrawl Search API

Before integrating the Firecrawl API with the Kimi K2 model, we need to verify how the Firecrawl Search API works and what outputs it generates.

We will request 5 search results for flights from New York to Tokyo and retrieve the latest results.

search_result = firecrawl_client.search(
    "Find flight from New York to Tokyo",
    limit=5,
    tbs="qdr:w",  # results from the past week
    timeout=30000,  # 30 seconds
)

for item in search_result.data:
    print("Title:", item["title"])
    print("URL:", item["url"])
    print("Description:", item["description"])
    print("-" * 40)

As a result, we received the titles, URLs, and descriptions of 5 flight details:

Title: American Airlines(r) - Find New York to Tokyo flights
URL: https://www.aa.com/en-us/flights-from-new-york-to-tokyo
Description: Find deals on New York to Tokyo flights ... *Fares displayed have been collected within the last 24hrs and may no longer be available at time of booking. Some ...
----------------------------------------
Title: Flights from New York to Tokyo (JFK - HND) - EVA Air
URL: https://flights.evaair.com/en/flights-from-new-york-to-tokyo
Description: Find New York to Tokyo Flights with EVA Air from USD 1,288. Round Trip ... Flight Type Round Trip|Economy. Dec 2025. No results available. Check ...
----------------------------------------
Title: Flights from New York to Tokyo | Singapore Airlines
URL: https://www.singaporeair.com/en-us/flights-from-new-york-to-tokyo
Description: Discover the best flight rates from New York to Tokyo. Travel in comfort with award-winning inflight services and state-of-the-art amenities.
----------------------------------------
Title: New York to Tokyo Flights | ANA
URL: https://flights.ana.co.jp/en-us/flights-from-new-york-to-tokyo
Description: Get a low fare flight from New York to Tokyo with ANA! Enjoy total comfort, world-class meals, and entertainment on your flight with ANA.
----------------------------------------
Title: Flights New York - Tokyo (NYC-TYO) - Air France
URL: https://wwws.airfrance.us/en-us/flights-from-new-york-nyc-to-tokyo
Description: Take a look at the next 6 months and find the best price to fly with Air France from New York (NYC) to Tokyo (TYO) or directly pick your departure date.
----------------------------------------

3. Testing Firecrawl Scrape API

Now let’s test the Scrape API. We will take the URL from the previous results and provide it to the Scrape API.

scrape_result = firecrawl_client.scrape_url(
    url="https://flights.evaair.com/en/flights-from-new-york-to-tokyo",
    formats=["markdown"],
    max_age=3600000,
)

# markdown content:
print(scrape_result.markdown[:500], "...")

As a result, we received the content of the webpage in markdown format:

[Skip to content](https://flights.evaair.com/en/flights-from-new-york-to-tokyo#main)- [Skip to footer](https://flights.evaair.com/en/flights-from-new-york-to-tokyo#footer)

# Find New York to Tokyo Flights with EVA Air from USD 1,288

Round Trip

_expand\_more_

1 Passenger, Economy

_expand\_more_

Departure City

_close_

Destination City

_close_

Departurefc-booking-departure-date-aria-label07/24/2025

_today_

Returnfc-booking-return-date-aria-label07/31/2025
...

Search

[![](https:// ...

4. Integrating Firecrawl API with Kimi K2

Next, we’ll integrate the Firecrawl API with the Kimi K2 model. For this experiment, we will be only using the Search API to achieve faster results.

  • Firecrawl API: Used to search flight information on the web.
  • Kimi K2 : Used to summarize and structure the flight search results in a user-friendly way.

The search_flights function uses the Firecrawl API to retrieve flight-related information based on a user query (e.g., “flights from New York to London”). The summarize_flight function takes the raw flight search results and requests Kimi K2 to summarize them in a structured, human-friendly format.

def search_flights(query: str, limit: int = 5):
    results = firecrawl_client.search(
        query,
        limit=limit,
        tbs="qdr:w",  # results from the past week
        timeout=30000,
    )
    jobs = []
    for item in results.data:
        jobs.append(
            {
                "title": item["title"],
                "url": item["url"],
                "description": item["description"],
            }
        )
    return jobs



def summarize_flight(description: str) -> str:
    messages = [
        {"role": "system", "content": "You are a helpful assistant."},
        {
            "role": "user",
            "content": f"""You are a helpful assistant. Summarize each flight search result into:
• Airline  
• Route (origin to destination)  
• Price (if available)  
• Key features or restrictions  
• Link to book flight
{description}""",
        },
    ]

    resp = groq_client.chat.completions.create(
        model="moonshotai/kimi-k2-instruct",
        messages=messages,
        max_tokens=512,
        temperature=0.7,
    )
    return resp.choices[0].message.content.strip()

The flight_search function calls search_flights to obtain raw flight data, passes this data to summarize_flight for structured summarization, and returns the final user-friendly summary:

def flight_search(query: str) -> str:
    flights = search_flights(query)
    summary = summarize_flight(str(flights))
    return summary

This app can also be built using an agentic framework like LangGraph, which allows the AI to make autonomous decisions about when to search, what information to gather, and how to process results using tools and agents. To learn more about top AI agent frameworks, please review The Best Open Source Frameworks For Building AI Agents in 2025.

5. Testing the Flight Search AI Application

Now that our Flight Search AI Application is set up, let’s test its performance by providing a sample user query:

result = flight_search("Find flight from New York to Tokyo")
print(result)

Each flight option is clearly summarized, including the airline, route, price (when available), key features or restrictions, and a direct booking link:

• Airline: American Airlines  
  Route: New York (JFK/EWR/LGA) → Tokyo (NRT/HND)  
  Price: Not specified in search feed ("...may no longer be available...")  
  Key features/restrictions: 24-hr price volatility warning; fare may change at booking  
  Link: https://www.aa.com/en-us/flights-from-new-york-to-tokyo  

• Airline: EVA Air  
  Route: New York (JFK) → Tokyo Haneda (HND)  
  Price: From USD 1,288 round-trip (Economy)  
  Key features/restrictions: Lowest price shown for Dec 2025 currently unavailable--check calendar  
  Link: https://flights.evaair.com/en/flights-from-new-york-to-tokyo  

• Airline: Singapore Airlines  
  Route: New York (JFK/EWR) → Tokyo (NRT/HND)  
  Price: Not displayed in search snippet  
  Key features/restrictions: Award-winning service, modern amenities, wide-body aircraft  
  Link: https://www.singaporeair.com/en-us/flights-from-new-york-to-tokyo  

• Airline: Air France  
  Route: New York (NYC-area airports) → Tokyo (TYO - both NRT/HND)  
  Price: "Best price" shown on 6-month calendar (not quoted in snippet)  
  Key features/restrictions: Flexible date selector; can mix cabin classes  
  Link: https://wwws.airfrance.us/en-us/flights-from-new-york-nyc-to-tokyo  

• Airline: ANA (All Nippon Airways)  
  Route: New York (JFK/EWR) → Tokyo (NRT/HND)  
  Price: Promoted as "low fare" but amount not listed  
  Key features/restrictions: Japanese hospitality, complimentary meals & entertainment  
  Link: https://flights.ana.co.jp/en-us/flights-from-new-york-to-tokyo

Creating the UI for the Travel Deal Finder AI Application

We are going to create a user-friendly web interface using Gradio that allows users to search for and summarize the best flight deals between two cities. In the app.py script, the user interface is built using Gradio’s Blocks API, which provides flexible layout and component arrangement options. The interface features text boxes where users can input their origin and destination cities, a checkbox to enable or disable “Deep Search” (which triggers detailed scraping of top results), and a button to initiate the search. When the user clicks “Find Deals,” the app disables the button to prevent duplicate submissions and displays a “Processing…” message.

app.py:

import os
import time

import gradio as gr
from firecrawl import FirecrawlApp
from groq import Groq

# Initialize API clients
firecrawl_client = FirecrawlApp(api_key=os.getenv("FIRECRAWL_API_KEY"))
groq_client = Groq(api_key=os.getenv("GROQ_API_KEY"))


def search_flights(origin: str, destination: str, limit: int = 5):
    query = f"Find flights from {origin} to {destination}"
    results = firecrawl_client.search(
        query,
        limit=limit,
        tbs="qdr:w",  # results from the past week
        timeout=30000,
    )
    flights = []
    for item in results.data:
        flights.append(
            {
                "title": item["title"],
                "url": item["url"],
                "description": item["description"],
            }
        )
    return flights


def summarize_flights(flights):
    messages = [
        {"role": "system", "content": "You are a helpful assistant."},
        {
            "role": "user",
            "content": f"""
Summarize these flight search results in clear, visually appealing markdown. For each flight, use the following format:

---
## [Airline Name]

- **Route:** [Origin] → [Destination]
- **Price:** [Price or 'Not quoted']
- **Key Points:** [Key features or restrictions]
- **Book:** [Link with airline name](URL)

---

{flights}
""",
        },
    ]
    resp = groq_client.chat.completions.create(
        model="moonshotai/kimi-k2-instruct",
        messages=messages,
        max_tokens=512,
        temperature=0.7,
    )
    return resp.choices[0].message.content.strip()


def scrape_flight_details(url: str):
    try:
        scrape_result = firecrawl_client.scrape_url(
            url=url,
            formats=["markdown"],
            max_age=3600000,
        )
        content = getattr(scrape_result, "markdown", None)
        if not content:
            return "No markdown content returned from scrape."
        content = content[:1500]  # limit for display
        # Summarize scraped content
        messages = [
            {"role": "system", "content": "You are a helpful assistant."},
            {
                "role": "user",
                "content": f"Summarize the key details from this flight booking page for a traveler.\n{content}",
            },
        ]
        resp = groq_client.chat.completions.create(
            model="moonshotai/kimi-k2-instruct",
            messages=messages,
            max_tokens=512,
            temperature=0.7,
        )
        return resp.choices[0].message.content.strip()
    except Exception as e:
        import traceback

        tb = traceback.format_exc()
        return f"Error scraping details: {type(e).__name__}: {e}\nTraceback:\n{tb}"


def travel_deal_finder(origin, destination, deep_search):
    flights = search_flights(origin, destination)
    summary = summarize_flights(str(flights))
    scraped_details = "No results to scrape."
    if deep_search:
        for flight in flights:
            url = flight["url"]
            details = scrape_flight_details(url)
            if not details.startswith("Error scraping details"):
                scraped_details = details
                break
    else:
        scraped_details = (
            "Deep Search is disabled. Only summarized search results are shown above."
        )
    return summary, scraped_details


def travel_deal_finder_with_time(origin, destination, deep_search):
    start = time.time()
    summary, scraped_details = travel_deal_finder(origin, destination, deep_search)
    elapsed = time.time() - start
    return (
        summary,
        scraped_details,
        gr.update(interactive=True),  # Re-enable button
        f"⏱️ Processing time: {elapsed:.2f} seconds",
    )


def main():
    with gr.Blocks() as demo:
        gr.Markdown(
            "# Travel Deal Finder ✈️\nEnter your origin and destination to find and summarize the best flight deals!"
        )
        with gr.Row():
            origin = gr.Textbox(label="Origin City", value="New York")
            destination = gr.Textbox(label="Destination City", value="Tokyo")
        deep_search = gr.Checkbox(
            label="Deep Search (scrape top results for details)", value=False
        )
        search_btn = gr.Button("Find Deals")
        summary_output = gr.Markdown(label="Flight Deals Summary")
        scrape_output = gr.Markdown(label="Top Result Details (Scraped)")
        time_output = gr.Markdown(label="Processing Time")

        def on_search(o, d, ds):
            # Disable button immediately
            return (
                gr.update(),  # summary_output placeholder
                gr.update(),  # scrape_output placeholder
                gr.update(interactive=False),  # Disable button
                "Processing...",  # Show processing message
            )

        search_btn.click(
            on_search,
            inputs=[origin, destination, deep_search],
            outputs=[summary_output, scrape_output, search_btn, time_output],
            queue=False,
        )

        search_btn.click(
            travel_deal_finder_with_time,
            inputs=[origin, destination, deep_search],
            outputs=[summary_output, scrape_output, search_btn, time_output],
            queue=True,
        )

    demo.launch()


if __name__ == "__main__":
    main()

To launch the app, simply run python app.py, and Gradio will start a local web server, making the Travel Deal Finder accessible in your browser at http://127.0.0.1:7860.

python app.py

Output:

* Running on local URL:  http://127.0.0.1:7860
* To create a public link, set `share=True` in `launch()`.

Copy and paste the http://127.0.0.1:7860 URL in your browser and view the Travel Deal Finder UI.

Travel Deal Finder Running

If you are facing issues running the app, please refer to the kingabzpro/Travel-with-Kimi-K2 GitHub repository, which contains code, examples, and a guide to clone and run the application locally.

Deploying the Travel Deal Finder AI Application

To make your Travel Deal Finder AI app accessible online, you can deploy it using Hugging Face Spaces. Spaces provides free hosting for interactive machine learning apps built with Gradio, Streamlit, or Docker.

  1. Go to https://huggingface.co/new-space and fill out the repository import form. Make sure to include the app’s name, description, license, and SDK, and then create your Space.

Create new huggingface Space

  1. After that, you will see a guide on how to deploy your app. The most popular solution is to clone the repository, add all the app files, and then push these files to the remote repository.

  2. Clone the repository from Hugging Face. git clone https://huggingface.co/spaces/your_account/name_of_your_project

  3. Create or update the requirements.txt file in the project root directory and add the following dependencies: groq==0.30.0 firecrawl-py==2.16.1

  4. Copy the app.py file you created during the previous session to the repository.

  5. Edit the README.md file based on your preferences.

Readme image

  1. Stage the changes, commit, and push the files to the remote Space repository:
git add .
git commit -m "initial commit"
git push

Note that for your password, you’ll need to enter a Hugging Face access token. 8. Go to your app’s settings and scroll down to add the necessary secrets. Input your Groq and Firecrawl API keys with the names GROQ_API_KEY and FIRECRAWL_API_KEY.

Variables and secrets

Once you save the secrets, your app will be ready, and you will see the proper user interface. You can test it by providing city names, and it will generate results within 5-10 seconds.

Travel Deal Finder Running

Screenshot from Travel With Kimi K2 If you encounter any issues while deploying the app, feel free to refer to the Travel With Kimi K2 example and duplicate the app to try it on your own account with your own API keys.

Conclusion

In this tutorial, we learned about the new fast and efficient Firecrawl Search API. We also learned how to use the Search and Scrape API to build a Travel Deal Finder AI application using Kimi K2, Firecrawl API and Gradio. In only a few steps, we built an easy-to-use app that provides details about the top five searches for specific travel destinations as well as a deep search option to perform a page scrape to gather even more details about your flight search.

Kimi K2 represents a major win for the open-source community. People can now quantize and run the model locally. Despite its size, the open-source release means users can choose from multiple providers based on their needs and performance. This flexibility also helps teams with budgeting and efficiency, rather than relying on a single proprietary provider. If you are interested in building more complex AI applications using Firecrawl, then please check out the LangGraph Tutorial: Build a Startup Idea Validator with Interactive UI.

Ready to Build?

Start scraping web data for your AI apps today.
No credit card needed.

About the Author

Abid Ali Awan image
Abid Ali Awan@1abidaliawan

I am a certified data scientist who enjoys building machine learning applications and writing blogs on data science. I am currently focusing on content creation, editing, and working with large language models.

More articles by Abid Ali Awan