{"id":22,"date":"2025-10-20T19:28:55","date_gmt":"2025-10-20T19:28:55","guid":{"rendered":"https:\/\/pulki.es\/blog\/?p=22"},"modified":"2025-10-20T19:28:55","modified_gmt":"2025-10-20T19:28:55","slug":"usando-file_search-con-responses-api","status":"publish","type":"post","link":"https:\/\/pulki.es\/blog\/index.php\/2025\/10\/20\/usando-file_search-con-responses-api\/","title":{"rendered":"Usando file_search con Responses API"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Puesto que <strong>Responses API<\/strong> es relativamente nueva, ChatGPT a\u00fan no ha interiorizado c\u00f3mo utilizar correctamente <strong>file_search<\/strong>. Por este motivo, explicar esta funcionalidad ser\u00e1 el objetivo de esta entrada.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Primero que todo, <strong>file_search<\/strong> es una herramienta que permite a los modelos buscar informaci\u00f3n relevante en tus archivos para, posteriormente, generar la respuesta. Evidentemente, para usarla hay que subir el archivo que queremos leer; por tanto, la primera variable a considerar es el formato de este.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Seg\u00fan la documentaci\u00f3n oficial, para archivos de texto la codificaci\u00f3n debe ser <strong>UTF-8<\/strong>, <strong>UTF-16<\/strong> o <strong>ASCII<\/strong>. Adicionalmente, las extensiones soportadas que no son de texto vienen dadas por <strong>.doc<\/strong>, <strong>.docx<\/strong>, <strong>.pdf<\/strong> y <strong>.pptx<\/strong>. Entonces, supongamos que contamos con un archivo con estas caracter\u00edsticas. Con el objetivo de que nuestro archivo sea le\u00eddo por <strong>file_search<\/strong>, tenemos que llevar a cabo cuatro pasos: crear un <em>vector store<\/em>, subir el archivo, enlazar el archivo al <em>vector store<\/em> y realizar la consulta.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Podemos empezar creando el <em>vector store<\/em> o subiendo el archivo, puesto que el orden entre ambos pasos no es relevante. Para ilustrar la idea, empezaremos con la creaci\u00f3n del <em>vector store<\/em>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em><strong>Creando un vector store<\/strong><\/em>&#8230;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Tomando el ejemplo de la <a href=\"https:\/\/platform.openai.com\/docs\/api-reference\/vector-stores\/create\">documentaci\u00f3n<\/a>, nuestro <em>request<\/em> viene dado por:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>curl https:\/\/api.openai.com\/v1\/vector_stores \\\n-H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n-H \"Content-Type: application\/json\" \\\n-H \"OpenAI-Beta: assistants=v2\" \\\n-d '{\n\"name\": \"Support FAQ\"\n}'<\/code><\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">donde <code>$OPENAI_API_KEY<\/code> es nuestra API key. Una respuesta hipot\u00e9tica viene dada por:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"id\": \"vs_abc123\",\n  \"object\": \"vector_store\",\n  \"created_at\": 1699061776,\n  \"name\": \"Support FAQ\",\n  \"description\": \"Contains commonly asked questions and answers, organized by topic.\",\n  \"bytes\": 139920,\n  \"file_counts\": {\n    \"in_progress\": 0,\n    \"completed\": 3,\n    \"failed\": 0,\n    \"cancelled\": 0,\n    \"total\": 3\n  }\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">De aquella respuesta, nos interesa el <strong>ID<\/strong>, que en este ejemplo es \u00abvs_abc123\u00bb. Una vez guardado, el paso siguiente es subir el archivo. Nuevamente, utilizando el ejemplo de la documentaci\u00f3n, un <em>request<\/em> v\u00e1lido podr\u00eda venir dado por:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>curl https:\/\/api.openai.com\/v1\/files \\\n  -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n  -F purpose=\"fine-tune\" \\\n  -F file=\"@mydata.jsonl\"\n  -F expires_after&#91;anchor]=\"created_at\"\n  -F expires_after&#91;seconds]=2592000<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">donde <em>mydata.jsonl<\/em> es el nombre del archivo local. Una vez enviada esta consulta, la respuesta podr\u00eda venir dada por:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{<br>\"id\": \"file-abc123\",<br>\"object\": \"file\",<br>\"bytes\": 120000,<br>\"created_at\": 1677610602,<br>\"expires_at\": 1677614202,<br>\"filename\": \"mydata.jsonl\",<br>\"purpose\": \"fine-tune\",<br>}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">De esta respuesta debemos guardar el <strong>ID<\/strong>, que en este caso es \u00abfile-abc123\u00bb. Ahora, con el <code>vector_store_id<\/code> y el <code>file_id<\/code> en mano, estamos en condiciones de enlazar el archivo a nuestro <em>vector store<\/em>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em><strong>Enlazando el archivo al vector store<\/strong><\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Nuevamente, usando el ejemplo de la documentaci\u00f3n, un <em>request<\/em> ejemplo podr\u00eda ser:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>curl https:\/\/api.openai.com\/v1\/vector_stores\/vs_abc123\/files \\\n-H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n-H \"Content-Type: application\/json\" \\\n-H \"OpenAI-Beta: assistants=v2\" \\\n-d '{\n\"file_id\": \"file-abc123\"\n}'<\/code><\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">cuya respuesta vendr\u00eda dada por:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"id\": \"file-abc123\",\n  \"object\": \"vector_store.file\",\n  \"created_at\": 1699061776,\n  \"usage_bytes\": 1234,\n  \"vector_store_id\": \"vs_abcd\",\n  \"status\": \"completed\",\n  \"last_error\": null\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">En este momento, tenemos todos los ingredientes para consultar nuestro archivo con alg\u00fan modelo.  <\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong><em>Consultando nuestro archivo&#8230;<\/em><\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Para consultar el contenido de nuestro archivo, utilizaremos el modelo GPT-5, y Responses API. Una consulta simplificada podr\u00eda venir dada por la siguiente:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>curl https:\/\/api.openai.com\/v1\/responses \\<br>-H \"Content-Type: application\/json\" \\<br>-H \"Authorization: Bearer $OPENAI_API_KEY\" \\<br>-d '{<br>\"model\": \"gpt-5\",<br>\"instructions\": \"Eres un asistente de la empresa P\u00fclki, y debes responder preguntas sobre ella, y sobre c\u00f3mo implementar IA en diferentes contextos.\",<br>\"input\": \"\u00bfDe qu\u00e9 trata P\u00fclki?.\",<br>\"reasoning\": { \"effort\": \"low\" },<br>\"text\": { \"verbosity\": \"low\" },<br>\"max_output_tokens\": 500,<br>\"tools\": &#91;<br>{<br>\"type\": \"file_search\",<br>\"vector_store_ids\": &#91;\"'\"$VECTOR_STORE_ID\"'\"],<br>\"max_num_results\": 1<br>}<br>]<br>}'<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">En este <em>request<\/em>, <code>$VECTOR_STORE_ID<\/code> contiene el ID del <em>vector store<\/em> que creamos en el primer apartado. Como podemos ver, no es necesario hacer referencia a ning\u00fan <code>file_id<\/code>. <strong>file_search<\/strong> busca autom\u00e1ticamente entre los archivos enlazados con el vector y genera una respuesta en base a ello.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Jos\u00e9 Miguel Mu\u00f1oz Urra \u2013\u00a0<a href=\"mailto:jmunozu@pulki.es\">jmunozu@pulki.es<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong><em>Referencias<\/em><\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/platform.openai.com\/docs\/api-reference\/introduction\">https:\/\/platform.openai.com\/docs\/api-reference\/introduction<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/platform.openai.com\/docs\/guides\/tools-file-search\">https:\/\/platform.openai.com\/docs\/guides\/tools-file-search<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Puesto que Responses API es relativamente nueva, ChatGPT a\u00fan no ha interiorizado c\u00f3mo utilizar correctamente file_search. Por este motivo, explicar esta funcionalidad ser\u00e1 el objetivo de esta entrada. Primero que todo, file_search es una herramienta que permite a los modelos buscar informaci\u00f3n relevante en tus archivos para, posteriormente, generar la respuesta. Evidentemente, para usarla hay [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-22","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/pulki.es\/blog\/index.php\/wp-json\/wp\/v2\/posts\/22","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pulki.es\/blog\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pulki.es\/blog\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pulki.es\/blog\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/pulki.es\/blog\/index.php\/wp-json\/wp\/v2\/comments?post=22"}],"version-history":[{"count":1,"href":"https:\/\/pulki.es\/blog\/index.php\/wp-json\/wp\/v2\/posts\/22\/revisions"}],"predecessor-version":[{"id":23,"href":"https:\/\/pulki.es\/blog\/index.php\/wp-json\/wp\/v2\/posts\/22\/revisions\/23"}],"wp:attachment":[{"href":"https:\/\/pulki.es\/blog\/index.php\/wp-json\/wp\/v2\/media?parent=22"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pulki.es\/blog\/index.php\/wp-json\/wp\/v2\/categories?post=22"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pulki.es\/blog\/index.php\/wp-json\/wp\/v2\/tags?post=22"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}