Skip to content

Commit

Permalink
[Search] [Playground] View code Flyout (#180083)
Browse files Browse the repository at this point in the history
Updates view code flyout to contain:
- better working example of the python elasticsearch client and python
langchain example
- the template is updated based on the settings chosen by the developer
- dependencies for pip install updated

<img width="979" alt="image"
src="https://github.com/elastic/kibana/assets/49480/663c0163-4ece-4fbd-812b-5535309ce7db">

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
  • Loading branch information
joemcelroy and kibanamachine authored Apr 5, 2024
1 parent 7d44ff6 commit 132dd4d
Show file tree
Hide file tree
Showing 13 changed files with 492 additions and 56 deletions.
8 changes: 8 additions & 0 deletions x-pack/plugins/search_playground/common/routes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

export const MANAGEMENT_API_KEYS = '/app/management/security/api_keys';
3 changes: 3 additions & 0 deletions x-pack/plugins/search_playground/kibana.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
"navigation",
"security"
],
"optionalPlugins": [
"cloud"
],
"requiredBundles": [
"kibanaReact"
]
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { render } from '@testing-library/react';
import { PY_LANG_CLIENT } from './py_lang_client'; // Adjust the import path according to your project structure
import { ES_CLIENT_DETAILS } from '../view_code_flyout';
import { CloudSetup } from '@kbn/cloud-plugin/public';
import { ChatForm } from '../../../types';

describe('PY_LANG_CLIENT function', () => {
test('renders with correct content', () => {
// Mocking necessary values for your function
const formValues = {
elasticsearch_query: { query: {} },
indices: ['index1', 'index2'],
docSize: 10,
source_fields: { index1: ['field1'], index2: ['field2'] },
prompt: 'Your prompt',
citations: true,
summarization_model: 'Your-new-model',
} as unknown as ChatForm;

const clientDetails = ES_CLIENT_DETAILS({
elasticsearchUrl: 'http://my-local-cloud-instance',
} as unknown as CloudSetup);

const { container } = render(PY_LANG_CLIENT(formValues, clientDetails));

expect(container.firstChild?.textContent).toMatchSnapshot();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { EuiCodeBlock } from '@elastic/eui';
import React from 'react';
import { ChatForm } from '../../../types';
import { Prompt } from '../../../../common/prompt';

const getESQuery = (query: any) => {
try {
return JSON.stringify(query, null, 2).replace('"${query}"', 'f"${query}"');
} catch (e) {
// eslint-disable-next-line no-console
console.error('Error parsing ES query', e);
return '{}';
}
};

export const PY_LANG_CLIENT = (formValues: ChatForm, clientDetails: string) => (
<EuiCodeBlock language="py" isCopyable overflowHeight="100%">
{`## Install the required packages
## pip install -qU elasticsearch openai
import os
from elasticsearch import Elasticsearch
from openai import OpenAI
${clientDetails}
openai_client = OpenAI(
api_key=os.environ["OPENAI_API_KEY"],
)
def get_elasticsearch_results(query):
es_query = ${getESQuery(formValues.elasticsearch_query.query)}
result = es.search(index="${formValues.indices.join(',')}", query=es_query, size=${
formValues.docSize
})
return result["hits"]["hits"]
def create_openai_prompt(question, results):
context = ""
index_source_fields = ${JSON.stringify(formValues.source_fields, null, 2)}
for hit in results:
source_field = index_source_fields.get(hit["_index"])[0]
hit_context = hit["_source"][source_field]
context += f"{hit_context}\n"
prompt = f"""${Prompt(formValues.prompt, {
context: true,
citations: formValues.citations,
type: 'openai',
})}"""
return prompt
def generate_openai_completion(user_prompt):
response = openai_client.chat.completions.create(
model="${formValues.summarization_model}",
messages=[
{"role": "system", "content": "You are an assistant for question-answering tasks."},
{"role": "user", "content": user_prompt},
]
)
return response.choices[0].message.content
if __name__ == "__main__":
question = "my question"
elasticsearch_results = get_elasticsearch_results(question)
context_prompt = create_openai_prompt(question, elasticsearch_results)
openai_completion = generate_openai_completion(context_prompt)
print(openai_completion)
`}
</EuiCodeBlock>
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { render } from '@testing-library/react';
import { ES_CLIENT_DETAILS } from '../view_code_flyout';
import { CloudSetup } from '@kbn/cloud-plugin/public';
import { ChatForm } from '../../../types';
import { LANGCHAIN_PYTHON } from './py_langchain_python';

describe('PY_LANGCHAIN function', () => {
test('renders with correct content', () => {
// Mocking necessary values for your function
const formValues = {
elasticsearch_query: { query: {} },
indices: ['index1', 'index2'],
docSize: 10,
source_fields: { index1: ['field1'], index2: ['field2'] },
prompt: 'Your prompt',
citations: true,
summarization_model: 'Your-new-model',
} as unknown as ChatForm;

const clientDetails = ES_CLIENT_DETAILS({
elasticsearchUrl: 'http://my-local-cloud-instance',
} as unknown as CloudSetup);

const { container } = render(LANGCHAIN_PYTHON(formValues, clientDetails));

expect(container.firstChild?.textContent).toMatchSnapshot();
});
});
Loading

0 comments on commit 132dd4d

Please sign in to comment.