@@ -61,7 +61,7 @@ ready. As a last step, we'll activate the environment and get started.
6161
6262 .. note ::
6363 Make sure to source the environment every time you open a new terminal
64- session before running `python `, `gel ` or `fastapi `-related commands.
64+ session before running `` python `` , `` gel `` or `` fastapi ` `-related commands.
6565
6666
6767Step 2. Get started with FastAPI
@@ -72,12 +72,12 @@ At this stage we need to follow FastAPI's `tutorial
7272
7373We're going to make a super simple web API with one endpoint that takes in a
7474user query as an input and echoes it as an output. First, let's make a directory
75- called `app ` in our project root, and put an empty `__init__.py ` there.
75+ called `` app `` in our project root, and put an empty `` __init__.py ` ` there.
7676
7777.. code-block :: bash
7878 $ mkdir app && touch app/__init__.py
7979
80- Create a file called `main.py ` inside the `app ` directory and put the "Hello
80+ Create a file called `` main.py `` inside the `` app ` ` directory and put the "Hello
8181World" example in it:
8282
8383.. code-block :: python
@@ -98,7 +98,7 @@ To start the server, run:
9898 $ fastapi dev app/main.py
9999
100100 Once the server gets up and running, we can make sure it works using FastAPI's
101- built-in UI at <http://127.0.0.1:8000/docs>_, or manually by using `curl `:
101+ built-in UI at <http://127.0.0.1:8000/docs>_, or manually by using `` curl ` `:
102102
103103.. code-block :: bash
104104 $ curl -X ' GET' \
@@ -119,7 +119,7 @@ uses Pydantic types to automatically figure out schemae for `input
119119<https://fastapi.tiangolo.com/tutorial/body/> `_, as well as `output
120120<https://fastapi.tiangolo.com/tutorial/response-model/> `_.
121121
122- Let's add the following to our `main.py `:
122+ Let's add the following to our `` main.py ` `:
123123
124124.. code-block :: python
125125 :caption: app/ main.py
@@ -142,7 +142,7 @@ argument and return type.
142142 return SearchResult(response = search_terms.query)
143143
144144 Same as before, we can test the endpoint using the UI, or by sending a request
145- with `curl `:
145+ with `` curl ` `:
146146
147147.. code-block :: bash
148148 $ curl -X ' POST' \
@@ -168,7 +168,7 @@ There're many powerful feature-rich products for LLM-driven web search (such as
168168Brave for example). But for purely educational purposes in this tutorial we'll
169169be sailing on the high seas 🏴☠️and scraping Google search results
170170directly. Google tends to actively resist such behavior, so the most reliable
171- way for us to get our search results is to employ the `googlesearch-python `
171+ way for us to get our search results is to employ the `` googlesearch-python ` `
172172library:
173173
174174.. code-block :: bash
@@ -242,9 +242,9 @@ result should look similar to this:
242242 if __name__ == " __main__" :
243243 print (fetch_web_sources(" gel database" , limit = 1 )[0 ][0 ])
244244
245- Feel free to grab this snippet and save it to `app/web.py `, or make your own.
245+ Feel free to grab this snippet and save it to `` app/web.py ` `, or make your own.
246246
247- Good enough for now! We need to add two extra dependencies: `requests ` for
247+ Good enough for now! We need to add two extra dependencies: `` requests ` ` for
248248making HTTP requests, and Beautiful Soup, which is a commonly used HTML parsing
249249library. Let's add them by running:
250250
@@ -352,11 +352,11 @@ generation like this:
352352
353353 Note that this cloud LLM API (and many others) requires a secret key to be set
354354as an environment variable. A common way to manage those is to use the
355- `python-dotenv ` library in combinations with a `.env ` file. Feel free to browse
356- `the readme
355+ `` python-dotenv `` library in combinations with a `` .env `` file. Feel free to
356+ browse `the readme
357357<https://github.com/theskumar/python-dotenv?tab=readme-ov-file#getting-started> `_,
358- although it's also quite simple to use. Create a file called `.env ` in the root
359- directory and put your api key in there:
358+ although it's also quite simple to use. Create a file called `` .env `` in the
359+ root directory and put your api key in there:
360360
361361.. code-block :: bash
362362 :caption: .env
@@ -423,14 +423,14 @@ Defining the schema
423423
424424The database :ref: `schema <_ref_datamodel_index >` in Gel is defined
425425declaratively. The :ref: `gel project init <_ref_cli_edgedb_project_init >`
426- command has created a file called `dbchema/default.esdl `, which we're going to
426+ command has created a file called `` dbchema/default.esdl ` `, which we're going to
427427use to define our types.
428428
429429We obviously want to keep track of messages, so we need to represent those in
430430the schema. By convention established in the LLM space, each message is going to
431431have a role in addition to the message content itself. We can also get Gel to
432432automatically keep track of message's creation time by adding a property callled
433- `timestamp ` and setting its :ref: `default value <_ref_datamodel_props >` to the
433+ `` timestamp ` ` and setting its :ref: `default value <_ref_datamodel_props >` to the
434434output of the :ref: `datetime_current() <_ref_std_datetime >` function. Finally,
435435LLM messages in our searchbot have souce URLs associated with them. Let's keep
436436track of those too, by adding a :ref: `multi-link property
@@ -456,7 +456,7 @@ schema too.
456456
457457 And chats all belong to a certain user, making up their chat history. One other
458458thing we'd like to keep track of about our users is their username, and it would
459- make sense for us to make sure that it's unique by using an `excusive `
459+ make sense for us to make sure that it's unique by using an `` excusive ` `
460460:ref: `constraint <_ref_datamodel_constraints >`.
461461
462462
@@ -591,7 +591,7 @@ the shell:
591591 };
592592 EOF
593593
594- This created an `app/sample_data/inserts.edgeql` file, which we can now execute
594+ This created an `` app/sample_data/inserts.edgeql` ` file, which we can now execute
595595using the CLI like this:
596596
597597.. code-block:: bash
@@ -624,12 +624,12 @@ generate typesafe function that we can plug directly into out Python code. If
624624you are completely unfamiliar with EdgeQL, now is a good time to check out the
625625basics before proceeding.
626626
627- Let's move on. First, create a directory inside `app` called `queries`. This is
628- where we're going to put all of the EdgeQL-related stuff.
627+ Let's move on. First, create a directory inside `` app`` called `` queries`` . This
628+ is where we're going to put all of the EdgeQL-related stuff.
629629
630630We're going to start by writing a query that fetches all of the users. In
631- `queries` create a file named `get_users.edgeql` and put the following query in
632- there:
631+ `` queries`` create a file named `` get_users.edgeql`` and put the following query
632+ in there:
633633
634634.. code-block:: edgeql
635635 :caption: app/queries/get_users.edgeql
@@ -641,9 +641,9 @@ Now run the code generator from the shell:
641641.. code-block:: bash
642642 $ gel-py
643643
644- It's going to automatically locate the `.edgeql` file and generate types for it.
645- We can inspect generated code in `app.queries/get_users_async_edgeql.py`. Once
646- that is done, let's use those types to create the endpoint in `main.py`:
644+ It's going to automatically locate the `` .edgeql`` file and generate types for
645+ it. We can inspect generated code in `` app.queries/get_users_async_edgeql.py``.
646+ Once that is done, let's use those types to create the endpoint in `` main.py` `:
647647
648648.. code-block:: python
649649 from edgedb import create_async_client
@@ -677,27 +677,27 @@ Let's verify it that works as expected:
677677
678678While we're at it, let's also implement the option to fetch a user by their
679679username. In order to do that, we need to write a new query in a separate file
680- `app/queries/get_user_by_name.edgeql`:
680+ `` app/queries/get_user_by_name.edgeql` `:
681681
682682.. code-block:: edgeql
683683 :caption: app/queries/get_users.edgeql
684684
685685 select User { name }
686686 filter .name = <str>$name;
687687
688- After that, we will run the code generator again by calling `gel-py`. In the
688+ After that, we will run the code generator again by calling `` gel-py` `. In the
689689app, we are going to reuse the same endpoint that fetches the list of all users.
690690From now on, if the user calls it without any arguments (e.g.
691- `http://127.0.0.1/users`), they are going to receive the list of all users, same
692- as before. But if they pass a username as a query argument like this:
693- `http://127.0.0.1/users?username=bob`, the system will attempt to fetch a user
694- named `bob`.
691+ `` http://127.0.0.1/users`` ), they are going to receive the list of all users,
692+ same as before. But if they pass a username as a query argument like this:
693+ `` http://127.0.0.1/users?username=bob` `, the system will attempt to fetch a user
694+ named `` bob` `.
695695
696- In order to achieve this, we're going to need to add a `Query`-type argument to
697- our endpoint function. You can learn more about how to configure this type of
696+ In order to achieve this, we're going to need to add a `` Query`` -type argument
697+ to our endpoint function. You can learn more about how to configure this type of
698698arguments in `FastAPI's docs
699699<https://fastapi.tiangolo.com/tutorial/query-params/>`_. It's default value is
700- going to be `None`, which will enable us to implement our conditional logic:
700+ going to be `` None` `, which will enable us to implement our conditional logic:
701701
702702.. code-block:: python
703703 :caption: app/main.py
@@ -741,8 +741,8 @@ And once again, let's verify that everything works:
741741
742742
743743Finally, let's also implement the option to add a new user. For this, just as
744- before, we'll create a new file `app/queries/create_user.edgeql`, add a query to
745- it and run code generation.
744+ before, we'll create a new file `` app/queries/create_user.edgeql`` , add a query
745+ to it and run code generation.
746746
747747.. code-block:: edgeql
748748 select(
@@ -753,12 +753,12 @@ it and run code generation.
753753 name
754754 }
755755
756- Note that in this query we've wrapped the `insert` in a `select` statement. This
757- is a common pattern in EdgeQL, that can be used whenever you would like to get
758- something other than object ID when you just inserted it.
756+ Note that in this query we've wrapped the `` insert`` in a `` select`` statement.
757+ This is a common pattern in EdgeQL, that can be used whenever you would like to
758+ get something other than object ID when you just inserted it.
759759
760760In order to integrate this query into our app, we're going to add a new
761- endpoint. Note that this one has the same name `/users`, but is for the POST
761+ endpoint. Note that this one has the same name `` /users` `, but is for the POST
762762HTTP method.
763763
764764.. code-block:: python
@@ -889,10 +889,10 @@ below if you are in rush.
889889 return await get_messages_query(gel_client, username=username, chat_id=chat_id)
890890
891891
892- For the `post_messages` function we're going to do something a little bit
892+ For the `` post_messages` ` function we're going to do something a little bit
893893different though. Since this is now the primary way for the user to add their
894- queries to the system, it functionally superceeds the `/search` endpoint we made
895- before. To this end, this function is where we're going to handle saving
894+ queries to the system, it functionally superceeds the `` /search`` endpoint we
895+ made before. To this end, this function is where we're going to handle saving
896896messages, retrieving chat history, invoking web search and generating the
897897answer.
898898
@@ -935,7 +935,7 @@ answer.
935935 return search_result
936936
937937
938- Let's not forget to modify the `generate_answer` function, so it can also be
938+ Let's not forget to modify the `` generate_answer` ` function, so it can also be
939939history-aware.
940940
941941.. code-block:: python
@@ -1110,7 +1110,7 @@ working on our query rather than rewriting it from scratch every time.
11101110This is what we need to do: every time the user submits a message, we need to
11111111fetch the chat history, extract a search query from it using the LLM, and the
11121112other steps are going to the the same as before. Let's make the follwing
1113- modifications to the `main.py`:
1113+ modifications to the `` main.py` `:
11141114
11151115.. code-block:: python
11161116 :caption: app/main.py
@@ -1209,8 +1209,8 @@ what they are looking for.
12091209Gel enables us to implement such a system with only minor modifications to the
12101210schema.
12111211
1212- We begin by enabling the `ai ` extension by adding the following like on top of
1213- the `dbschema/default.esdl`:
1212+ We begin by enabling the ``ai` ` extension by adding the following like on top of
1213+ the `` dbschema/default.esdl` `:
12141214
12151215.. code-block:: sdl
12161216 using extension ai;
@@ -1224,7 +1224,7 @@ the `dbschema/default.esdl`:
12241224
12251225Next, we need to configure the API key in Gel for whatever embedding provider
12261226we're going to be using. As per documentation, let's open up the CLI by typing
1227- `gel` and run the following command (assuming we're using OpenAI):
1227+ `` gel` ` and run the following command (assuming we're using OpenAI):
12281228
12291229.. code-block:: edgeql
12301230 searchbot:main> configure current database
@@ -1262,7 +1262,7 @@ Gel's AI documentation and take a look at instance logs:
12621262 INFO 50121 searchbot 2025-01-30T14:39:53.364 httpx: HTTP Request: POST https://api.openai.com/v1/embeddings "HTTP/1.1 200 OK"
12631263
12641264It's time to create the second half of the similarity search - the search query.
1265- The query needs to fetch `k ` chats in which there're messages that are most
1265+ The query needs to fetch ``k` ` chats in which there're messages that are most
12661266similar to our current message. This can be a little difficult to visualize in
12671267your head, so here's the query itself:
12681268
@@ -1286,8 +1286,8 @@ your head, so here's the query itself:
12861286 order by .distance
12871287 limit <int64>$limit;
12881288
1289- Let's place in in `app/queries/search_chats.edgeql`, run the codegen and modify
1290- our `post_messages` endpoint to keep track of those similar chats.
1289+ Let's place in in `` app/queries/search_chats.edgeql` `, run the codegen and modify
1290+ our `` post_messages` ` endpoint to keep track of those similar chats.
12911291
12921292.. code-block:: python
12931293 from edgedb.ai import create_async_ai, AsyncEdgeDBAI
0 commit comments