We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Bug: openapi render for multiple tags isn't consistent
**Describe the bug**
When the openapi renders tags from both a controller and a route it is not deterministic. This may not be a bug? But it surprised me so thought I'd raise it.

I'm unsure if I'm doing something crazy but for a project, we check in the generated json openapi schema so we can browse the API live in gitlab. I've recently added a tag to both a controller and a route in it. But because the order of the tags isn't consistent they are going to keep flip flopping as we have a pre-commit that generates the json to make sure it's up to date. I hope that ramble makes sense...

**To Reproduce**
```python
from typing import Dict                                           
                                                                  
from starlite import Starlite, Controller, get                    
                                                                  
class TestController(Controller):                                 
    tags = ["a"]                                                  
                                                                  
    @get("/", tags=["b"])                                         
    def hello_world(self) -> Dict[str, str]:                      
        """Handler function that returns a greeting dictionary."""
        return {"hello": "world"}                                 
                                                                  
                                                                  
app = Starlite(route_handlers=[TestController])                   
print(app.openapi_schema.paths["/"].get.tags)                     
```
If you run that multiple times, you will see you get either:
```python
['a', 'b']
```
or
```python
['b', 'a']
```

**Additional context**
I believe the problem is [here](https://github.com/starlite-api/starlite/blob/835749112e8364c1516f45973c924774aca22ca9/starlite/openapi/path_item.py#L59) as it forces construction of a new set. Sorting them before returning would be viable as there shouldn't be _too many_ tags and it's a one time thing I believe?

But as I said, it may not be a problem you care about as I could be doing something silly.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `starlite/openapi/path_item.py`
Content:
```
1 from inspect import cleandoc
2 from typing import TYPE_CHECKING, Dict, List, Optional, Tuple, cast
3 
4 from pydantic_openapi_schema.v3_1_0.operation import Operation
5 from pydantic_openapi_schema.v3_1_0.path_item import PathItem
6 
7 from starlite.openapi.parameters import create_parameter_for_handler
8 from starlite.openapi.request_body import create_request_body
9 from starlite.openapi.responses import create_responses
10 from starlite.utils.helpers import unwrap_partial
11 
12 if TYPE_CHECKING:
13     from pydantic import BaseModel
14     from pydantic_openapi_schema.v3_1_0 import SecurityRequirement
15 
16     from starlite.handlers import HTTPRouteHandler
17     from starlite.plugins.base import PluginProtocol
18     from starlite.routes import HTTPRoute
19 
20 
21 def get_description_for_handler(route_handler: "HTTPRouteHandler", use_handler_docstrings: bool) -> Optional[str]:
22     """Produce the operation description for a route handler, either by using the description value if provided,
23 
24     or the docstring - if config is enabled.
25 
26     Args:
27         route_handler: A route handler instance.
28         use_handler_docstrings: If `True` and `route_handler.description` is `None` returns docstring of wrapped
29             handler function.
30 
31     Returns:
32         An optional description string
33     """
34     handler_description = route_handler.description
35     if handler_description is None and use_handler_docstrings:
36         fn = unwrap_partial(route_handler.fn.value)
37         return cleandoc(fn.__doc__) if fn.__doc__ else None
38     return handler_description
39 
40 
41 def extract_layered_values(
42     route_handler: "HTTPRouteHandler",
43 ) -> Tuple[Optional[List[str]], Optional[List[Dict[str, List[str]]]]]:
44     """Extract the tags and security values from the route handler layers.
45 
46     Args:
47         route_handler: A Route Handler instance.
48 
49     Returns:
50         A tuple of optional lists.
51     """
52     tags: List[str] = []
53     security: List["SecurityRequirement"] = []
54     for layer in route_handler.ownership_layers:
55         if layer.tags:
56             tags.extend(layer.tags)
57         if layer.security:
58             security.extend(layer.security)
59     return list(set(tags)) if tags else None, security or None
60 
61 
62 def create_path_item(
63     route: "HTTPRoute", create_examples: bool, plugins: List["PluginProtocol"], use_handler_docstrings: bool
64 ) -> PathItem:
65     """Create a PathItem model for the given route parsing all http_methods into Operation Models."""
66     path_item = PathItem()
67     for http_method, handler_tuple in route.route_handler_map.items():
68         route_handler, _ = handler_tuple
69         if route_handler.include_in_schema:
70             handler_fields = cast("BaseModel", route_handler.signature_model).__fields__
71             parameters = (
72                 create_parameter_for_handler(
73                     route_handler=route_handler,
74                     handler_fields=handler_fields,
75                     path_parameters=route.path_parameters,
76                     generate_examples=create_examples,
77                 )
78                 or None
79             )
80             raises_validation_error = bool("data" in handler_fields or path_item.parameters or parameters)
81             handler_name = unwrap_partial(route_handler.handler_name).replace("_", " ").title()
82             request_body = None
83             if "data" in handler_fields:
84                 request_body = create_request_body(
85                     field=handler_fields["data"], generate_examples=create_examples, plugins=plugins
86                 )
87 
88             tags, security = extract_layered_values(route_handler)
89             operation = Operation(
90                 operationId=route_handler.operation_id or handler_name,
91                 tags=tags,
92                 summary=route_handler.summary,
93                 description=get_description_for_handler(route_handler, use_handler_docstrings),
94                 deprecated=route_handler.deprecated,
95                 responses=create_responses(
96                     route_handler=route_handler,
97                     raises_validation_error=raises_validation_error,
98                     generate_examples=create_examples,
99                     plugins=plugins,
100                 ),
101                 requestBody=request_body,
102                 parameters=parameters,  # type: ignore[arg-type]
103                 security=security,
104             )
105             setattr(path_item, http_method.lower(), operation)
106     return path_item
107
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/starlite/openapi/path_item.py b/starlite/openapi/path_item.py
--- a/starlite/openapi/path_item.py
+++ b/starlite/openapi/path_item.py
@@ -56,7 +56,7 @@
             tags.extend(layer.tags)
         if layer.security:
             security.extend(layer.security)
-    return list(set(tags)) if tags else None, security or None
+    return sorted(set(tags)) if tags else None, security or None
 
 
 def create_path_item(

{"golden_diff": "diff --git a/starlite/openapi/path_item.py b/starlite/openapi/path_item.py\n--- a/starlite/openapi/path_item.py\n+++ b/starlite/openapi/path_item.py\n@@ -56,7 +56,7 @@\n             tags.extend(layer.tags)\n         if layer.security:\n             security.extend(layer.security)\n-    return list(set(tags)) if tags else None, security or None\n+    return sorted(set(tags)) if tags else None, security or None\n \n \n def create_path_item(\n", "issue": "Bug: openapi render for multiple tags isn't consistent\n**Describe the bug**\r\nWhen the openapi renders tags from both a controller and a route it is not deterministic. This may not be a bug? But it surprised me so thought I'd raise it.\r\n\r\nI'm unsure if I'm doing something crazy but for a project, we check in the generated json openapi schema so we can browse the API live in gitlab. I've recently added a tag to both a controller and a route in it. But because the order of the tags isn't consistent they are going to keep flip flopping as we have a pre-commit that generates the json to make sure it's up to date. I hope that ramble makes sense...\r\n\r\n**To Reproduce**\r\n```python\r\nfrom typing import Dict                                           \r\n                                                                  \r\nfrom starlite import Starlite, Controller, get                    \r\n                                                                  \r\nclass TestController(Controller):                                 \r\n    tags = [\"a\"]                                                  \r\n                                                                  \r\n    @get(\"/\", tags=[\"b\"])                                         \r\n    def hello_world(self) -> Dict[str, str]:                      \r\n        \"\"\"Handler function that returns a greeting dictionary.\"\"\"\r\n        return {\"hello\": \"world\"}                                 \r\n                                                                  \r\n                                                                  \r\napp = Starlite(route_handlers=[TestController])                   \r\nprint(app.openapi_schema.paths[\"/\"].get.tags)                     \r\n```\r\nIf you run that multiple times, you will see you get either:\r\n```python\r\n['a', 'b']\r\n```\r\nor\r\n```python\r\n['b', 'a']\r\n```\r\n\r\n**Additional context**\r\nI believe the problem is [here](https://github.com/starlite-api/starlite/blob/835749112e8364c1516f45973c924774aca22ca9/starlite/openapi/path_item.py#L59) as it forces construction of a new set. Sorting them before returning would be viable as there shouldn't be _too many_ tags and it's a one time thing I believe?\r\n\r\nBut as I said, it may not be a problem you care about as I could be doing something silly.\r\n\n", "before_files": [{"content": "from inspect import cleandoc\nfrom typing import TYPE_CHECKING, Dict, List, Optional, Tuple, cast\n\nfrom pydantic_openapi_schema.v3_1_0.operation import Operation\nfrom pydantic_openapi_schema.v3_1_0.path_item import PathItem\n\nfrom starlite.openapi.parameters import create_parameter_for_handler\nfrom starlite.openapi.request_body import create_request_body\nfrom starlite.openapi.responses import create_responses\nfrom starlite.utils.helpers import unwrap_partial\n\nif TYPE_CHECKING:\n    from pydantic import BaseModel\n    from pydantic_openapi_schema.v3_1_0 import SecurityRequirement\n\n    from starlite.handlers import HTTPRouteHandler\n    from starlite.plugins.base import PluginProtocol\n    from starlite.routes import HTTPRoute\n\n\ndef get_description_for_handler(route_handler: \"HTTPRouteHandler\", use_handler_docstrings: bool) -> Optional[str]:\n    \"\"\"Produce the operation description for a route handler, either by using the description value if provided,\n\n    or the docstring - if config is enabled.\n\n    Args:\n        route_handler: A route handler instance.\n        use_handler_docstrings: If `True` and `route_handler.description` is `None` returns docstring of wrapped\n            handler function.\n\n    Returns:\n        An optional description string\n    \"\"\"\n    handler_description = route_handler.description\n    if handler_description is None and use_handler_docstrings:\n        fn = unwrap_partial(route_handler.fn.value)\n        return cleandoc(fn.__doc__) if fn.__doc__ else None\n    return handler_description\n\n\ndef extract_layered_values(\n    route_handler: \"HTTPRouteHandler\",\n) -> Tuple[Optional[List[str]], Optional[List[Dict[str, List[str]]]]]:\n    \"\"\"Extract the tags and security values from the route handler layers.\n\n    Args:\n        route_handler: A Route Handler instance.\n\n    Returns:\n        A tuple of optional lists.\n    \"\"\"\n    tags: List[str] = []\n    security: List[\"SecurityRequirement\"] = []\n    for layer in route_handler.ownership_layers:\n        if layer.tags:\n            tags.extend(layer.tags)\n        if layer.security:\n            security.extend(layer.security)\n    return list(set(tags)) if tags else None, security or None\n\n\ndef create_path_item(\n    route: \"HTTPRoute\", create_examples: bool, plugins: List[\"PluginProtocol\"], use_handler_docstrings: bool\n) -> PathItem:\n    \"\"\"Create a PathItem model for the given route parsing all http_methods into Operation Models.\"\"\"\n    path_item = PathItem()\n    for http_method, handler_tuple in route.route_handler_map.items():\n        route_handler, _ = handler_tuple\n        if route_handler.include_in_schema:\n            handler_fields = cast(\"BaseModel\", route_handler.signature_model).__fields__\n            parameters = (\n                create_parameter_for_handler(\n                    route_handler=route_handler,\n                    handler_fields=handler_fields,\n                    path_parameters=route.path_parameters,\n                    generate_examples=create_examples,\n                )\n                or None\n            )\n            raises_validation_error = bool(\"data\" in handler_fields or path_item.parameters or parameters)\n            handler_name = unwrap_partial(route_handler.handler_name).replace(\"_\", \" \").title()\n            request_body = None\n            if \"data\" in handler_fields:\n                request_body = create_request_body(\n                    field=handler_fields[\"data\"], generate_examples=create_examples, plugins=plugins\n                )\n\n            tags, security = extract_layered_values(route_handler)\n            operation = Operation(\n                operationId=route_handler.operation_id or handler_name,\n                tags=tags,\n                summary=route_handler.summary,\n                description=get_description_for_handler(route_handler, use_handler_docstrings),\n                deprecated=route_handler.deprecated,\n                responses=create_responses(\n                    route_handler=route_handler,\n                    raises_validation_error=raises_validation_error,\n                    generate_examples=create_examples,\n                    plugins=plugins,\n                ),\n                requestBody=request_body,\n                parameters=parameters,  # type: ignore[arg-type]\n                security=security,\n            )\n            setattr(path_item, http_method.lower(), operation)\n    return path_item\n", "path": "starlite/openapi/path_item.py"}], "after_files": [{"content": "from inspect import cleandoc\nfrom typing import TYPE_CHECKING, Dict, List, Optional, Tuple, cast\n\nfrom pydantic_openapi_schema.v3_1_0.operation import Operation\nfrom pydantic_openapi_schema.v3_1_0.path_item import PathItem\n\nfrom starlite.openapi.parameters import create_parameter_for_handler\nfrom starlite.openapi.request_body import create_request_body\nfrom starlite.openapi.responses import create_responses\nfrom starlite.utils.helpers import unwrap_partial\n\nif TYPE_CHECKING:\n    from pydantic import BaseModel\n    from pydantic_openapi_schema.v3_1_0 import SecurityRequirement\n\n    from starlite.handlers import HTTPRouteHandler\n    from starlite.plugins.base import PluginProtocol\n    from starlite.routes import HTTPRoute\n\n\ndef get_description_for_handler(route_handler: \"HTTPRouteHandler\", use_handler_docstrings: bool) -> Optional[str]:\n    \"\"\"Produce the operation description for a route handler, either by using the description value if provided,\n\n    or the docstring - if config is enabled.\n\n    Args:\n        route_handler: A route handler instance.\n        use_handler_docstrings: If `True` and `route_handler.description` is `None` returns docstring of wrapped\n            handler function.\n\n    Returns:\n        An optional description string\n    \"\"\"\n    handler_description = route_handler.description\n    if handler_description is None and use_handler_docstrings:\n        fn = unwrap_partial(route_handler.fn.value)\n        return cleandoc(fn.__doc__) if fn.__doc__ else None\n    return handler_description\n\n\ndef extract_layered_values(\n    route_handler: \"HTTPRouteHandler\",\n) -> Tuple[Optional[List[str]], Optional[List[Dict[str, List[str]]]]]:\n    \"\"\"Extract the tags and security values from the route handler layers.\n\n    Args:\n        route_handler: A Route Handler instance.\n\n    Returns:\n        A tuple of optional lists.\n    \"\"\"\n    tags: List[str] = []\n    security: List[\"SecurityRequirement\"] = []\n    for layer in route_handler.ownership_layers:\n        if layer.tags:\n            tags.extend(layer.tags)\n        if layer.security:\n            security.extend(layer.security)\n    return sorted(set(tags)) if tags else None, security or None\n\n\ndef create_path_item(\n    route: \"HTTPRoute\", create_examples: bool, plugins: List[\"PluginProtocol\"], use_handler_docstrings: bool\n) -> PathItem:\n    \"\"\"Create a PathItem model for the given route parsing all http_methods into Operation Models.\"\"\"\n    path_item = PathItem()\n    for http_method, handler_tuple in route.route_handler_map.items():\n        route_handler, _ = handler_tuple\n        if route_handler.include_in_schema:\n            handler_fields = cast(\"BaseModel\", route_handler.signature_model).__fields__\n            parameters = (\n                create_parameter_for_handler(\n                    route_handler=route_handler,\n                    handler_fields=handler_fields,\n                    path_parameters=route.path_parameters,\n                    generate_examples=create_examples,\n                )\n                or None\n            )\n            raises_validation_error = bool(\"data\" in handler_fields or path_item.parameters or parameters)\n            handler_name = unwrap_partial(route_handler.handler_name).replace(\"_\", \" \").title()\n            request_body = None\n            if \"data\" in handler_fields:\n                request_body = create_request_body(\n                    field=handler_fields[\"data\"], generate_examples=create_examples, plugins=plugins\n                )\n\n            tags, security = extract_layered_values(route_handler)\n            operation = Operation(\n                operationId=route_handler.operation_id or handler_name,\n                tags=tags,\n                summary=route_handler.summary,\n                description=get_description_for_handler(route_handler, use_handler_docstrings),\n                deprecated=route_handler.deprecated,\n                responses=create_responses(\n                    route_handler=route_handler,\n                    raises_validation_error=raises_validation_error,\n                    generate_examples=create_examples,\n                    plugins=plugins,\n                ),\n                requestBody=request_body,\n                parameters=parameters,  # type: ignore[arg-type]\n                security=security,\n            )\n            setattr(path_item, http_method.lower(), operation)\n    return path_item\n", "path": "starlite/openapi/path_item.py"}]}