Nova postagem

Pesquisar

Pergunta
· jan 29, 2024

Service Unavailable when Authenticating through Apache/Web Gateway and LDAP

Lately my group has been seeing issues when signing in through the Management Portal or VS Code we are getting "Service Unavailable" errors returned to us. We recently migrated away from using the PWS to using Apache/InterSystems Web Gateway and using LDAP instead of Delegated Authentication. 

I have been on the hunt to find out where the problem might lie. When I run the "Test LDAP Authentication" from within the Management Portal, eventually I receive a response after getting a couple of timeouts while waiting for the response.

Authenticated user roth16 10 times in 26.177111 seconds - 0.382/sec

However, if I try to Authenticate through the Management Portal using my username, I get the "Service Unavailable" error. I have tried increasing the timeouts within the LDAP settings, and Web Gateway to no success. 

Does anyone have any suggestions on where to look to see the failure before I contact WRC?

1 Comment
Discussão (1)1
Entre ou crie uma conta para continuar
Artigo
· jan 29, 2024 12min de leitura

Load a recipe dataset with Foreign Tables and analyze it using LLMs with Embedded Python (Langchain + OpenAI)

We have a yummy dataset with recipes written by multiple Reddit users, however most of the information is free text as the title or description of a post. Let's find out how we can very easily load the dataset, extract some features and analyze it using features from OpenAI large language model within Embedded Python and the Langchain framework.

3 Comments
Discussão (3)3
Entre ou crie uma conta para continuar
Artigo
· jan 26, 2024 8min de leitura

PrivateGPT exploring the Documentation

Considering new business interest in applying Generative-AI to local commercially sensitive private data and information, without exposure to public clouds. Like a match needs the energy of striking to ignite, the Tech lead new "activation energy" challenge is to reveal how investing in GPU hardware could support novel competitive capabilities. The capability can reveal the use-cases that provide new value and savings.

Sharpening this axe begins with a functional protocol for running LLMs on a local laptop.

My local Mac has an M1 processor. In early experiments had found from exploring Falcon models the flow of toolkit was primarily towards using the Cuda graphics card. There are "compressed" versions of models ( Quantized ). However from my current exploration path these could only be loaded into a Cuda GPU which I didn't have. No Bit-and-bytes support for M1 / M2 processors and AutoGPTQ quantization didn't support MPS processor either. Running the unquantized models in CPU was prohibitively slow.

I had spotted PrivateGPT project and the following steps got things running.

# install developer tools
xcode-select --install 

# create python sandbox
mkdir PrivateGTP
cd privateGTP/
python3 -m venv .
# actiavte local context
source bin/activate

# privateGTP uses poetry for python module management
privateGTP> pip install poetry

# sync privateGTP project
privateGTP> git clone https://github.com/imartinez/privateGPT

# enable MPS for model loading and processing
privateGTP> CMAKE_ARGS="-DLLAMA_METAL=on" pip install --force-reinstall --no-cache-dir llama-cpp-python

privateGTP> cd privateGPT

# Import configure python dependencies
privateGTP> poetry run python3 scripts/setup

# launch web interface to confirm operational on default model
privateGTP> python3 -m private_gpt
# navigate safari browser to http://localhost:8001/

# To bulk import documentation needed to stop the web interface as vector database not in multi-user mode
privateGTP> [control] + "C"

# import some PDFs
privateGTP> curl "https://docs.intersystems.com/irislatest/csp/docbook/pdfs.zip" -o /tmp/pdfs.zip
privateGTP> unzip /tmp/pdfs.zip -d /tmp
# took a few hours to process
privateGTP> make ingest /tmp/pdfs/pdfs/

# launch web interface again for query documentation
privateGTP> python3 -m private_gpt

Experiments with the default model mistral-7B-Instruct

Some things that worked reasonably were looking for more textual content.

1. What is a lock Table?

2. Write Object Script "Hello World"

3. INSERT in SQL Statement

The trailing semicolon is a trained habit from training on different implementations of SQL.

Current deployed versions of IRIS would have an issue with the trailing semicolon but this is addressed as discarded rather that being an error in newer version specifically to address this common generative nuance.

4. ObjectScript FOR loop

The challenge here is treating the increment as the max counter. So it creates an endless loop incrementing by "10" instead of a loop that increments by "1" ten times. As a minor point the trailing quit is not necessary to the loop, but is tidy in terms of a well contained line label.

5 . ObjectScript continue

Here the use of documentation is clearly confused the ObjectScript with IRIS BASIC language examples ( THEN keyword ). A query docs approach, possibly needs to use "ObjectScript" as a metadata filter or have upstream generated sets of help PDFs that are limited to a particular language implementation. Anticipating Python and Java examples could impose a similar effect. The use of "i%2" is python syntax for modular operator where as would be expecting "i#2" for object script.

 

Swapping out models

New models can be added by downloading GGUF format models to the models sub-directory from https://huggingface.co/

Here the naming convention contained "Q"+level to indicate quantization loss versus size. Where lower "Q" is effectively a smaller download model with more quality loss.

settings.yaml

local:
  llm_hf_repo_id: TheBloke/Mistral-7B-Instruct-v0.1-GGUF
  llm_hf_model_file: mistral-7b-instruct-v0.1.Q4_K_M.gguf
  #llm_hf_repo_id: TheBloke/Orca-2-13B-GGUF
  #llm_hf_model_file: orca-2-13b.Q6_K.gguf
  #llm_hf_repo_id: TheBloke/XwinCoder-34B-GGUF
  #llm_hf_model_file: xwincoder-34b.Q6_K.gguf
  embedding_hf_model_name: BAAI/bge-small-en-v1.5ssss

Using "LLM Chat" mode ( No query documents) with "xwincoder-34b" model, suggests much "code" recommendations can come from the existing trained model.

It demonstrated an interesting learned confusion between Globals and Routines which both are referenced by the carrot ( "^" ) .

The enthusiasm for "%" prefix for method name invocation may be learned invocation patterns from system class documentation instead of learning the feature of method name relates to invoking said method.

There are configuration references with system management that undertake actions in the %SYS namespace and this is generally quite separate from activities of third-party code.

It was interesting to see the invocation as well as implementation example to uncover such disparity ( Invoked as a Routine instead of class method ).

General Generative capabilities ( Model Orca 13b Q6 )

1. Generating questions and answers from supplied text

2. Explaining differences of concepts from supplied text

3. Summarizing information into a shorter form

Integrate with IRIS

PrivateGPT can be put to work from IRIS by exercising available JSON end point with surprisingly little code.

The following code snippets demonstrate direct usage from ObjectScript.

This can easily be wrapped by IRIS Integration Operations and Messages to provide a reusable facility with configuration, message trace, etc.,.

IRIS Conversation example

// Construct a request message via IRIS building Dynamic Object in ObjectScript
    // The property "use_context" = true, this ensures that preloaded documents are searched
    // for similarity, autoloaded into context to support response generation
    // The property "prompt", This is the full prompt provided to the LLM
    Set request={"use_context":true,"prompt":"What is an IRIS lock table"}
    // Using %Net.HttpRequest for direct access
    Set hr=##class(%Net.HttpRequest).%New()
    Set hr.Server="127.0.0.1"
    Set hr.Port=8001
    Set hr.ContentType="application/json"
   
    Do hr.SetHeader("Accept","application/json")
    // Embed the request as JSON
    Do hr.EntityBody.Write(request.%ToJSON())
    // Make request
    // The optional "2" argument causes the response to be output to the default device ( terminal )
    // Useful for analysing returned output
    Do hr.Post("/v1/completions",2)
    // The stream should already be rewound, but stated here
    // should stream need to be reused in testing
    Do hr.HttpResponse.Data.Rewind()
    // Turn the response back into IRIS %Dynamic Object
    Set response={}.%FromJSON(hr.HttpResponse.Data.Read(32000))
    // Grab the generated response
    Set outputMessage=response.choices.%Get(0).message
    // Grab the metadata for references used by generation
    Set outputSources=response.choices.%Get(0).sources.%Get(0).document
   
    Write !,"Output:",outputMessage.content
    Write !,"File reference:",outputSources."doc_metadata"."page_label"
    Write !,"Filename:",outputSources."doc_metadata"."file_name"

Example output:

 

IRIS Retrieve Embedding Example

// Construct a request message via IRIS building Dynamic Object Construct
    Set textForEmbedding={"input":"This is some test text from IRIS database"}
    // Using %Net.HttpRequest for direct access
    Set hr=##class(%Net.HttpRequest).%New()
    Set hr.Server="127.0.0.1"
    Set hr.Port=8001
    Set hr.ContentType="application/json"
    Do hr.SetHeader("Accept","application/json")
    // Embedd the request as JSON
    Do hr.EntityBody.Write(textForEmbedding.%ToJSON())
    // Make request
    // The optional "2" argument causes the response to be output to the default device ( terminal )
    // Useful for analysing returned output
    Do hr.Post("/v1/embeddings",2)
    // The stream should already be rewound, but stated here
    // should stream need to be reused in testing
    Do hr.HttpResponse.Data.Rewind()
    // Turn the response back into IRIS %Dynamic Object
    Set response={}.%FromJSON(hr.HttpResponse.Data.Read(32000))
    // Example of iterator to loop over embeddings array
    Set iter=response.data.%Get(0).embedding.%GetIterator()
    // Output of floating point numbers of the returned embedding
    While iter.%GetNext(.key, .value, .type) {
        Write !,"key=",key,", value=",value,", type=",type
    }

Example output:

Further IRIS integration

The web API also supports:

  • dynamically loading new source documents
  • listing existing source document
  • deleting existing source documents
  • a health API to indicate availability

Further details available at: https://docs.privategpt.dev/api-reference/api-reference/ingestion

Summary thoughts and ideas

Local inference ( running quantized LLMs on laptop for productivity ) can be a useful way to initially scale the application of existing and internally retrained models. It allows flexibility for business users to privately explore and share new usercases and prompt engineering recipes.

To use PrivateGPT better for documentation, would need to delve deeper to reconfigure generative temperature lower, to reduce the creativity and improve accuracy of answers.

Technical Documentation and user manuals are no longer intended simply for human readers.

Can existing documentation pipelines be easily repurposed with metadata to shape documentation output that is better consumed and repurposed for generative AI?

A single documentation resource for multiple code languages makes it difficult to generalize usefully without conflating code examples. Hence hypothesis is that both documentation "code language" and "source retraining" of models would be better suited in short-term to be mono-code-language resources and assistants.

How well can retraining an existing model "unlearn" existing code conflations to be replaced with the useful and expected code syntax?

Hope this inspires new explorations.

References

Martínez Toro, I., Gallego Vico, D., & Orgaz, P. (2023). PrivateGPT [Computer software]. https://github.com/imartinez/privateGPT

Resources

https://github.com/imartinez/privateGPT

https://docs.privategpt.dev/

https://huggingface.co/models

https://github.com/ggerganov/llama.cpp

3 Comments
Discussão (3)2
Entre ou crie uma conta para continuar
InterSystems Oficial
· jan 26, 2024 2min de leitura

Cómo instalar Apache en sistemas operativos compatibles con IRIS

Para vuestra comodidad, InterSystems está publicando los pasos de instalación característicos de los sistemas operativos que son compatibles con InterSystems IRIS.

Para Microsoft Windows, consultad por favor la documentación de producto de InterSystems.

El instalador de IRIS detectará si hay un servidor web instalado en la misma máquina, lo que da la opción de tener configurado automáticamente el servidor web.

Todas las instalaciones de Apache requerirán permiso de sudo (recomendado) o de root para instalar el servidor web. Este requisito es compatible con las mejores prácticas recomendadas.

Para Red Hat (RHEL), InterSystems está instalando ficheros SELinux para admitir conexiones a través de http o https (si están configuradas).

Opcionalmente los scritps proporcionan instrucciones sobre cómo convertir los pasos de instalación en un fichero ejecutable (el nombre del fichero solo es una recomendación).

InterSystems ofrece tres vídeos y un podcast con información adicional y ejemplos de uso.

Esperamos que el nuevo proceso os resulte rápido, sencillo y claro. Cambiar el procedimiento no fue una decisión fácil, pero era requerido a menudo por los clientes y está en línea con las mejores prácticas.

Una vez que hayáis cambiado del Servidor Web Privado, probablemente es tan fácil como instalar apps en vuestros dispositivos móviles.

Instrucciones de instalación

Fichero script para Ubuntu

# instalar o actualizar apache2

sudo apt install apache2 -y

# habilitar e iniciar httpd

sudo service apache2 start --now

apache2 -v

Fichero script para RedHat

# instalar o actualizar httpd

sudo dnf install httpd -y

# habilitar e iniciar httpd

sudo systemctl enable --now httpd

sudo systemctl start httpd

httpd -v

# Confirmar el estado SELinux (que debería ser ejecuado)

getenforce

Fichero script para AIX

# instalar o actualizar httpd

sudo yum install httpd -y

# iniciará httpd

sudo /etc/rc.d/init.d/httpd start

httpd -v

Fichero script para SUSE

#  instalar o actualizar apache2

sudo systemctl enable apache2

# habilitará e iniciará apache2

sudo systemctl restart apache2

systemctl status apache2

Discussão (0)2
Entre ou crie uma conta para continuar
Artigo
· jan 24, 2024 9min de leitura

Database Driven IRIS Production with Custom Inbound Adapters

The traditional use of an IRIS production is for an inbound adapter to receive input from an external source, send that input to an IRIS service, then have that service send that input through the production.

With a custom inbound adapter though, we can make an IRIS production do more. We can use an IRIS production to process data from our own database without any external trigger.

By using an IRIS production in this way your data processing tasks now get to leverage all the built in features of an IRIS production, including:

  • Advanced tracking and monitoring
  • Multithreaded processing for scalability
  • Configuration based business logic
  • Built-in IRIS operations to quickly connect to external systems
  • Quick recovery from system failures

The documentation for making a custom inbound adapter can be found at: https://docs.intersystems.com/hs20231/csp/docbook/DocBook.UI.Page.cls?KEY=EGDV_adv#EGDV_adv_adapterdev_inbound

Let’s look at 3 examples of a simple production configured to process “Fish” objects from a database.

In the first example we will make a data driven production that will continually process data.

In the second example we will modify this production to process data only during specific times.

In the third example we will modify this production to process data only when triggered via a system task.

Example 1: Continual Data Processing

This example is a simple production configured to continually process “Fish” objects from a database. All the production does is continually look for new fish objects, convert those fish objects to JSON, and then spit that JSON out to a file.

First, we make the Fish object we intend to process:

Class Sample.Fish Extends (%Persistent, Ens.Util.MessageBodyMethods, %JSON.Adaptor, %XML.Adaptor)
{

Parameter ENSPURGE As %Boolean = 0;
Property Type As %String;
Property Size As %Numeric;
Property FirstName As %String;
Property Status As %String [ InitialExpression = "Initialized" ];
Index StatusIndex On Status;
}

Status is important as that is how we will track unprocessed Fish from processed.

Setting ENSPURGE to 0 will prevent this object from being purged along with the message headers in the future.

Second, we make a custom adapter to look for new Fish:

Class Sample.Adapter.FishMonitorAdapter Extends Ens.InboundAdapter
{

/// Fish status value the adapter will query for. All matching fish will have their status set to SetFishStatus and then will be sent to the service.
Property GetFishStatus As %String [ InitialExpression = "Initialized", Required ];
/// Fish status value the service will set fish to before they are sent to the service.
Property SetFishStatus As %String [ InitialExpression = "Processed", Required ];
Parameter SETTINGS = "GetFishStatus:Basic,SetFishStatus:Basic";
Parameter SERVICEINPUTCLASS = "Sample.Fish";
Method OnTask() As %Status
{
	//Cursor to seach for any matching fish
	set getFishStatus = ..GetFishStatus
	&sql(declare fishCursor cursor for
		select ID into :fishId
		from Sample.Fish
		where Status = :getFishStatus)
	
	//Execute the cursor
	&sql(open fishCursor)
	for {
		&sql(fetch fishCursor)
		quit:SQLCODE'=0
		//For each matching fish, change its Status and send it to the service (BusinessHost)
		set fishObj = ##class(Sample.Fish).%OpenId(fishId)
		set fishObj.Status = ..SetFishStatus
		$$$ThrowOnError(fishObj.%Save())
		$$$ThrowOnError(..BusinessHost.ProcessInput(fishObj))
	}
	&sql(close fishCursor)
	if SQLCODE < 0 {
		throw ##class(%Exception.SQL).CreateFromSQLCODE(SQLCODE,%msg)
	}
	
	quit $$$OK
}

The OnTask() method searches for any fish matching the configured GetFishStatus value. For each fish it finds it changes its status to the configured SetFishStatus value and then passes it to the service’s ProcessInput method.

Third, we make a custom service to use this adapter:

Class Sample.Service.FishMonitorService Extends Ens.BusinessService
{

/// Configuration item to which to send messages
Property TargetConfigName As Ens.DataType.ConfigName;
Parameter SETTINGS = "TargetConfigName:Basic";
Parameter ADAPTER = "Sample.Adapter.FishMonitorAdapter";
Method OnProcessInput(pInput As Sample.Fish, pOutput As %RegisteredObject) As %Status
{
    quit:..TargetConfigName=""
    //Send fish to configured target
    quit ..SendRequestAsync(..TargetConfigName, pInput)
}

}

This service takes fish as input and passes them via an async request to the configured target.

Fourth, we make a custom business process to convert the fish to JSON.

Class Sample.Process.FishToJSONProcess Extends Ens.BusinessProcess
{

/// Configuration item to which to send messages
Property TargetConfigName As Ens.DataType.ConfigName;
Parameter SETTINGS = "TargetConfigName:Basic";
Method OnRequest(pRequest As Sample.Fish, Output pResponse As Ens.Response) As %Status
{
	//Convert the fish to a JSON stream
	do pRequest.%JSONExportToStream(.jsonFishStream)
	//Make a new stream container with JSON stream
	set tRequest = ##class(Ens.StreamContainer).%New(jsonFishStream)
	//Send stream container to configured target
	quit ..SendRequestAsync(..TargetConfigName, tRequest, 0)
}

Method OnResponse(request As Ens.Request, ByRef response As Ens.Response, callrequest As Ens.Request, callresponse As Ens.Response, pCompletionKey As %String) As %Status
{
    quit $$$OK
}

}

The OnRequest() method is the only one that does anything. It accepts fish, generates a JSON stream from the fish, packages that stream into a Ens.StreamContainer, and then passes that stream container via an async request to the configured target.

Finally, we configure the production:

Class Sample.DataProduction Extends Ens.Production
{

XData ProductionDefinition
{
<Production Name="Sample.DataProduction" LogGeneralTraceEvents="false">
  <Description></Description>
  <ActorPoolSize>2</ActorPoolSize>
  <Item Name="Sample.Service.FishMonitorService" Category="" ClassName="Sample.Service.FishMonitorService" PoolSize="1" Enabled="true" Foreground="false" Comment="" LogTraceEvents="false" Schedule="">
    <Setting Target="Host" Name="TargetConfigName">Sample.Process.FishToJSONProcess</Setting>
  </Item>
  <Item Name="Sample.Process.FishToJSONProcess" Category="" ClassName="Sample.Process.FishToJSONProcess" PoolSize="1" Enabled="true" Foreground="false" Comment="" LogTraceEvents="false" Schedule="">
    <Setting Target="Host" Name="TargetConfigName">EnsLib.File.PassthroughOperation</Setting>
  </Item>
  <Item Name="EnsLib.File.PassthroughOperation" Category="" ClassName="EnsLib.File.PassthroughOperation" PoolSize="1" Enabled="true" Foreground="false" Comment="" LogTraceEvents="false" Schedule="">
    <Setting Target="Adapter" Name="FilePath">C:\temp\fish\</Setting>
  </Item>
</Production>
}

}

All that is left to do is to test it. For this we just need to open a terminal window and make a new fish object.

Looking at the production messages we can see the fish was found and processed:

We can inspect the trace of both messages:

And looking at the output folder (C:\temp\fish\) we can see the output file:

 

Example 2: Schedule-Based Data Processing

For use cases where we only want to process data at specific times, like overnight, we can configure the service to run on a schedule.

To modify example 1 to run on a schedule we first make a Schedule Spec. The documentation on how to do this can be found here: https://docs.intersystems.com/iris20231/csp/docbook/DocBook.UI.PortalHelpPage.cls?KEY=Ensemble%2C%20Schedule%20Editor

Then we change the service configuration to use this schedule:

Class Sample.DataProduction Extends Ens.Production
{

XData ProductionDefinition
{
<Production Name="Sample.DataProduction" LogGeneralTraceEvents="false">
  <Description></Description>
  <ActorPoolSize>2</ActorPoolSize>
  <Item Name="Sample.Service.FishMonitorService" Category="" ClassName="Sample.Service.FishMonitorService" PoolSize="1" Enabled="true" Foreground="false" Comment="" LogTraceEvents="false" Schedule="@Midnight Processing">
    <Setting Target="Host" Name="TargetConfigName">Sample.Process.FishToJSONProcess</Setting>
  </Item>
  <Item Name="Sample.Process.FishToJSONProcess" Category="" ClassName="Sample.Process.FishToJSONProcess" PoolSize="1" Enabled="true" Foreground="false" Comment="" LogTraceEvents="false" Schedule="">
    <Setting Target="Host" Name="TargetConfigName">EnsLib.File.PassthroughOperation</Setting>
  </Item>
  <Item Name="EnsLib.File.PassthroughOperation" Category="" ClassName="EnsLib.File.PassthroughOperation" PoolSize="1" Enabled="true" Foreground="false" Comment="" LogTraceEvents="false" Schedule="">
    <Setting Target="Adapter" Name="FilePath">C:\temp\fish\</Setting>
  </Item>
</Production>
}

}

Now when we look at this “Jobs” tab of the service we see there are no jobs running:

Form now on this service will only ever have jobs running between the hours of midnight and 1AM.

 

Example 3: Event-Based Data Processing with Task Manager

For use cases where we only want to process data once at a specific time or when a particular event takes place, we can configure the service to only execute when a system task is run.

To modify example 1 to run only when triggered by a task we first make a custom task to trigger the service.

Class Sample.Task.TriggerServiceTask Extends %SYS.Task.Definition
{

/// The name of the Business Service this task should run.
Property BuinessServiceName As %String [ Required ];
Method OnTask() As %Status
{
	#dim pBusinessService As Ens.BusinessService
	$$$ThrowOnError(##class(Ens.Director).CreateBusinessService(..BuinessServiceName, .pBusinessService))
	Quit pBusinessService.OnTask()
}

}

Second, we configure a new system task. Documentation on how to configure system tasks can be found here: https://docs.intersystems.com/iris20233/csp/docbook/Doc.View.cls?KEY=GSA_manage_taskmgr

This is the custom part of the configuration process for this example is:

In addition, I am configuring the task to be an on-demand task, but you could set up a schedule instead.

Finally, we configure the production:

Class Sample.DataProduction Extends Ens.Production
{

XData ProductionDefinition
{
<Production Name="Sample.DataProduction" LogGeneralTraceEvents="false">
  <Description></Description>
  <ActorPoolSize>2</ActorPoolSize>
  <Item Name="Sample.Service.FishMonitorService" Category="" ClassName="Sample.Service.FishMonitorService" PoolSize="0" Enabled="true" Foreground="false" Comment="" LogTraceEvents="false" Schedule="">
    <Setting Target="Host" Name="TargetConfigName">Sample.Process.FishToJSONProcess</Setting>
  </Item>
  <Item Name="Sample.Process.FishToJSONProcess" Category="" ClassName="Sample.Process.FishToJSONProcess" PoolSize="1" Enabled="true" Foreground="false" Comment="" LogTraceEvents="false" Schedule="">
    <Setting Target="Host" Name="TargetConfigName">EnsLib.File.PassthroughOperation</Setting>
  </Item>
  <Item Name="EnsLib.File.PassthroughOperation" Category="" ClassName="EnsLib.File.PassthroughOperation" PoolSize="1" Enabled="true" Foreground="false" Comment="" LogTraceEvents="false" Schedule="">
    <Setting Target="Adapter" Name="FilePath">C:\temp\fish\</Setting>
  </Item>
</Production>
}

}

Note that we set the PoolSize of Sample.Service.FishMonitorService to 0.

All that is left to do is to test it. For this we just need to open a terminal window and make a new fish object.

Looking at the production messages we can see the fish has not been processed yet:

Then we run the on-demand task to trigger the service:

Now looking at the production messages we can see the service was triggered causing the fish to be found and processed:

We can inspect the trace of both messages:

And looking at the output folder (C:\temp\fish\) we can see the output file:

 

Conclusion

The above examples are quite simple. You could configure the productions to do far more though. Including…

Basically, anything that could be done in a typical IRIS production could be done here too.

1 Comment
Discussão (1)1
Entre ou crie uma conta para continuar